LINQ查询以查找所有标记?

LINQ查询以查找所有标记?,linq,Linq,我有一个名为Notes的管理文档的应用程序。与博客一样,Notes可以搜索一个或多个标记的匹配项,这些标记包含在Notes.Tags集合属性中。标记具有名称和ID属性,并根据ID进行匹配。用户可以指定多个要匹配的标记,在这种情况下,注释必须包含指定要匹配的所有标记 我有一个非常复杂的LINQ查询来执行注释搜索,带有扩展方法和循环。坦率地说,它有一种真正的代码味道。我想用更简单的方法重写查询。我知道如果我把标签做成一个简单的字符串,我可以使用这样的东西: var matchingNotes = f

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

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

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

如果我的模型使用带有ID的标记对象,我可以做这么简单的事情吗?查询是什么样子的。它能用流利的语法书写吗?那会是什么样子?

首先请看我的评论;无论如何,我怀疑这个问题是错误的!我将简化它,只需单独强制每个标记存在:

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));
}
IQueryable查询=…//查询的顶部
foreach(searchTagId中的变量tagId){
var tmpId=tagId;//修改的闭包。。。
query=query.Where(note=>note.Tags.Any(t=>t.Id==tmpId));
}

这应该具有强制执行所有指定标记的净效果。我相信您可以在单个LINQ表达式中找到具有相关标记的注释:

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

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

这也不是很好。

Timwi的解决方案适用于LINQ的大多数方言,但不适用于LINQ to实体。我确实发现了一个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));
return searchTags.Aggregate(DataStore.ObjectContext.Notes,(current,tag)=>current.Where(n=>n.Tags.Any(t=>t.Id==tag.Id)).OrderBy(n=>n.Title));

我使用EntityFramework4从数据库中读取笔记集。DataStore是我用来管理EF4连接的自定义类;它将EF4 ObjectContext作为一个属性保存。

我认为您的查询并不像您所想的那样-它强制要求注释只使用指定的标记进行标记。它不会检查它是否具有所有指定的值…查询会引发以下错误:“无法创建“Tag”类型的常量值”。在此上下文中只支持基元类型(“如Int32、String和Guid”)。它对我来说很好,所以您的代码中一定有您没有告诉我们的内容。例如,你确定
Tag.Id
string
类型吗?实际上,TagID是GUID类型。@David Veeneman:我想我已经回答了你的问题。如果您认为我没有,请编辑问题以澄清仍缺少哪些信息。如果您还有其他问题,可以发布一个新的单独问题。我相信我发现了问题所在——问题出在LINQ to实体上,而不是您的查询。LTE中的All()方法似乎有问题。看,嗨,你能回答吗
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));