如何在自引用表中获得给定以下路由别名的最后一个类别

本文关键字:路由 别名 最后一个 自引用 | 更新日期: 2023-09-27 18:07:13

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

    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;

但这是发送许多查询..

我怎么做一个时间?

如何在自引用表中获得给定以下路由别名的最后一个类别

如果我明白你想要什么,你可以使用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));

首先,如果类别表很小,有时最好只是抓取整个表并在内存中进行选择(可能使用p.w.s.g的答案)。

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

但是,如果你真的想在Linq中这样做,那么我认为唯一的方法是反复添加一个连接到同一个表。

下面假设您的关系是在名为ParentID和Id的字段之间。我还更改了字符串permalink,以便更好地说明顺序。

首先需要一个小的辅助类

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和b),所以测试它并测试它的执行情况是很重要的。

我认为生成的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'

区段或别名越多,连接就越多。

现在您已经看到了所有这些,您可能想要避免使用这个方法-)

我可能只会增加你的困惑:),但让我只是抛出一个想法…
我只想说这不起作用(完全符合您的规范)-这不是解决方案,但可能会帮助您简化一些事情。

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' -从cat1 -到cat100 -它给出'cat6'…'cat1'(我指的是别名)

然而,它有一个主要的'缺陷'与'排序' -你的规格需要排序是'别名' as they come的顺序-这是一个有点不幸的查询。如果您能够以某种方式执行或定义一个可以转换为SQL的顺序,那么这个(或类似的)可能会起作用。

我假设-你的"别名"是按升序预先排序的订单-此查询工作。我知道他们不是这样的

但我认为你的想法在这里没有明确定义(以及为什么我们所有人都有问题)-思考,优化-简化您的需求-并让您的c#层帮助,例如通过预排序。

你也可以尝试某种形式的"分组"每只猫。别名等-但我认为同样的"排序问题"仍然存在。