在相交中执行包含

时间:2010-10-10 07:32:05

标签: c# linq

我有一个相当复杂的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(),它们都能很好地运行。

2 个答案:

答案 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