我有一个相当复杂的linq查询,它在项目的多对多关系中返回一个项目和一列的字符串[]。
所以我返回一个像这样的匿名类型:
var q = from k in db.Items
join m in db.ManyRel on k.Id equals m.ItemID
select new
{
k,
list = (from t in m
where t.ItemID == k.ID
select t.Name)
}
所以匿名类型是{IQueryable<k>, IQueryable<string>}
。
我当时想要做的是在列表中搜索string[] input
的交叉点。
q.Select(x => new
{
x.k,
PartialMatches = ?????,
ExactMatches = x.tags.Intersect(input).Count()
});
我目前使用.Intersect,但.Intersect()仅匹配整个元素。我想以某种方式在.Intersect()中使用.Contains()来计算部分匹配的数量。
如果可能的话,我宁愿在没有扩展方法的情况下这样做。
编辑:@Jon&amp; Timwi
我尝试了两个版本,它们几乎相同,并且他们发现输入中的任何项目部分存在于x.tags中。我希望能够计算输入中有多少项在x.tags中部分存在,而不仅仅是AN项是否存在。谢谢你的回复。
我认为我对AsEnumerable()的处理能力比几天前更好。
另外,对于记录,因为你好奇,Intersect()方法不会转换为Linq to SQL,也没有你提出的任何方法。但是,使用AsEnumberable(),它们都能很好地运行。
答案 0 :(得分:2)
嗯,表达的方式是:
PartialMatches = x.tags.Where(tag => input.Any(word => word.Contains(tag)))
(反之亦然 - 你还没有说过你希望遏制工作的方式)。
但是,我不希望将其成功转换为SQL ...我不能确定你可以让LINQ将其转换为SQL,我担心。
答案 1 :(得分:1)
您不需要使用Intersect
,也不需要对SQL进行转换。你可以用C#:
var results = q.AsEnumerable().Select(x => new
{
x.k,
PartialMatches = x.tags.Count(tag => input.Any(
word => word.Contains(tag))),
ExactMatches = x.tags.Intersect(input).Count()
});
对AsEnumerable()
的调用将数据库中的这部分查询分离。之前的所有内容都将从数据库中检索出来,其余内容将在C#中处理。
理论上,您可以在SQL中执行ExactMatches
(如果LINQ to SQL可以将其转换为SQL,我不确定它可以),但是这样做是否更有效并不明显在C#中做到这一点。这取决于所涉及的集合的相对大小,包括input
。