我的问题解决方法就像这样的代码;
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;
但这是多次查询..
我该怎么做一次?
答案 0 :(得分: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));
答案 1 :(得分:0)
首先,如果类别表很小,有时最好只抓住整个表并在内存中进行选择(可能使用p.w.s.g的答案)。
如果表很大,那么存储过程可能会比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和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'
部分或别名越多,那么连接就越多。
现在你已经看到了所有这些,你可能想避免使用这种方法 - )
答案 2 :(得分: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...
)。
e.g。如果你给它'cat1','cat2'......'cat6' - 从cat1到cat100 - 它给'cat6'...'cat1'(我的意思是别名)
然而,“排序”存在一个主要的“缺陷” - 您的规格要求排序是“别名”as they come
的顺序 - 这对查询来说有点不幸。如果您可以以某种方式强制执行或定义可以转换为SQL的订单,则此(或类似)可能有效。
我假设 - 你的'别名'是按升序预先排序的 order - 使此查询起作用。他们不是,我知道 这一点。
但我认为你的想法在这里没有明确定义(以及为什么我们所有人都遇到问题) - 仔细考虑并优化 - 简化您的要求 - 并让您的C#等级帮助,例如通过预先排序。
你也可以尝试某种形式的'分组'每只猫.Alias等 - 但我认为同样的'排序问题'仍然存在。