LINQ查询查找所有标签?

时间:2010-08-21 23:10:19

标签: linq

我有一个管理Notes文档的应用程序。像博客一样,Notes可以搜索与一个或多个标签的匹配,这些标签包含在Note.Tags集合属性中。标签具有名称和标识属性,并根据标识进行匹配。用户可以指定多个要匹配的标记,在这种情况下,Note必须包含指定匹配的所有标记。

我有一个非常复杂的LINQ查询来执行注释搜索,使用扩展方法和循环。坦率地说,它有一个真正的代码味道。我想用更简单的东西重写查询。我知道如果我把Tag变成一个简单的字符串,我可以使用这样的东西:

var matchingNotes = from n in myNotes
                    where n.Tags.All(tag => searchTags.Contains(tag))

如果我的模型使用带有ID的Tag对象,我可以做一些简单的事吗?查询会是什么样子。它可以用流利的语法编写吗?会是什么样的?

3 个答案:

答案 0 :(得分:3)

我相信您可以在单个LINQ表达式中找到具有相关标签的注释:

IQueryable<Note> query = ... // top part of query

query = query.Where(note => searchTags.All(st =>
    note.Tags.Any(notetag => notetag.Id == st.Id)));

不幸的是,AllAny没有相同的“流利语法”,所以你能做的最好的就是

query = from note in query
        where searchTags.All(st =>
            note.Tags.Any(notetag => notetag.Id == st.Id))
        select note;

也不是那么好。

答案 1 :(得分:0)

初学者看到我的评论;我怀疑查询错了!我简化它,只需单独强制执行每个标记:

IQueryable<Note> query = ... // top part of query
foreach(var tagId in searchTagIds) {
    var tmpId = tagId; // modified closures...
    query = query.Where(note => note.Tags.Any(t => t.Id == tmpId));
}

这应该具有强制执行指定的所有标签的净效果。

答案 2 :(得分:0)

Timwi的解决方案适用于LINQ的大多数方言,但不适用于Linq to Entities。我确实找到了一个单语句LINQ查询,它可以运行,由 ReSharper 提供。基本上,我写了一个foreach块来进行搜索,ReSharper提出将块转换为LINQ语句 - 我不知道它可以做到这一点。

我让ReSharper执行转换,这就是它给我的内容:

return searchTags.Aggregate<Tag, IQueryable<Note>>(DataStore.ObjectContext.Notes, (current, tag) => current.Where(n => n.Tags.Any(t => t.Id == tag.Id)).OrderBy(n => n.Title));

我使用Entity Framework 4从数据库中读取了我的Notes集合.DataStore是我用来管理EF4连接的自定义类;它将EF4 ObjectContext保存为属性。