2

我的问题像这样解决这样的代码;

    string permalink = "computers/hp/computers"; //example for similarity
    List<string> aliases = permalink.Split('/').ToList();

    Category cat = db.Categories.SingleOrDefault(c => c.Alias == aliases.First());
    aliases.Remove(aliases.First());

    foreach (string alias in aliases)
    {
        cat = cat.Categories.SingleOrDefault(c => c.Alias == alias);
    }

    return cat;

但这发送了许多查询..

我怎么做一次?

4

3 回答 3

0

如果我了解您想要什么,您可以使用该Enumerable.Aggregate方法。您必须从包含所有db.Categories. 不过,这很容易模拟。试试这个:

var aliases = permalink.Split('/');
var category = new Category // start with a 'root' category
{
    Id = 0, 
    Categories = db.Categories 
}; 
var cat = aliases.Aggregate(category, (c, a) => c.Categories.SingleOrDefault(x => x.Alias == a));
于 2013-04-03T19:21:22.693 回答
0

首先,如果类别表很小,有时最好只抓取整个表并在内存中进行选择(也许使用 pwsg 的答案)。

如果表很大,那么存储过程可能会比 Linq 更好。

但是,如果您真的想在 Linq 中执行此操作,那么我认为唯一的方法是重复向同一张表添加连接。

以下假设您的关系在称为 ParentID 和 Id 的字段之间。我还更改了您的字符串永久链接以更好地说明顺序。

你首先需要一个小助手类

public class Info
{
    public Category category;
    public int? recordID;
}

然后你的主要代码

string permalink ="computers1/hp/computers2"; 
var aliases = permalink.Split('/');

var query = dc.Categories.Where(r=>r.Alias == aliases[aliases.Length-1])
              .Select(r=> new Info { category = r,  recordID = r.ParentID});

    for(int i = aliases.Length -2 ; i >= 0; i--)
    {
        string alias = aliases[i]; 
        query =  query.Join(dc.Categories , 
                            a => a.recordID , b => b.Id , (a,b) => new { a , b} )
        .Where(r=>r.b.Alias == alias)
        .Select(r=> new Info { category = r.a.category, recordID = r.b.ParentID});
    }

    return query.SingleOrDefault().category;

正如你所看到的,join 的 lambda 语法是(恕我直言)可怕的,我通常会尽量避免它,但无论如何我都想不出在这里避免它。

由于我无法测试它,它可能是完全错误的(可能我混淆了 ID、ParentID 或我的 a's 和 b's ),因此测试它并测试它的性能很重要。

我认为产生的sql应该是这样的

SELECT * from Categories AS t0
INNER JOIN Categories AS t1 ON t0.ParentID = t1.id
INNER JOIN Categories AS t2 ON t1.ParentID = t2.id
WHERE t2.Alias = 'computers1' 
  AND t1.Alias = 'hp' 
  AND t0.Alias = 'computers2'

部分或别名越多,连接就越多。

既然您已经看到了所有这些,您可能希望避免使用这种方法 -)

于 2013-04-03T22:18:26.270 回答
0

我可能只会增加您的困惑:),但是让我提出一个想法...
让我说一下这行不通(完全按照您的规格)-这不是解决方案,但可能会帮助您简化事情有点。

var query = 
    (from cat in db.Categories
     where cat.Alias == "mainAalias"
     from subcat in cat.Categories
     where aliases.Contains(subcat.Alias)
     orderby subcat.Alias descending
     select subcat);  
query.FirstOrDefault(); // or something

这应该产生一个相对简单的查询
(例如SELECT...FROM...JOIN...WHERE... AND...IN...ORDERBY...)。

例如,如果你给它 'cat1', 'cat2'...'cat6' - out of cat1 - to cat100 - 它给出 'cat6'...'cat1' (我的意思是别名)

然而,它的“排序”有一个主要的“缺陷” ——您的规范需要一种“别名”顺序的排序as they come——这对于查询来说有点不幸。如果您能以某种方式强制执行或定义一个命令,那么可以将其转换为 SQL,这(或类似的)可能会起作用。

我假设-您的“别名”已按升序进行了预排序-此查询可以正常工作。他们不是,我知道这一点。

但我认为您的想法在这里没有明确定义(以及为什么我们所有人都遇到问题) - 仔细考虑并优化 - 简化您的要求 - 并让您的 C# 层提供帮助,例如通过预排序。

您也可以尝试对每个 cat.Alias 等进行某种形式的“分组”-但我认为同样的“排序问题”仍然存在。

于 2013-04-04T01:40:36.127 回答