2010-08-21 75 views
2

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

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

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

我可以做,如果我的简单模型使用Tag对象与ID的东西吗?查询是什么样的。它可以写成流利的语法吗?那将是什么样子?

+1

我不认为你的查询是按照你的想法进行的 - 它强制该注释是只用指定的标签**标记的。它不检查它是否具有*指定的所有* – 2010-08-21 23:16:21

+0

有趣 - 谢谢! – 2010-08-21 23:35:44

+0

http://stackoverflow.com/questions/3478874/how-do-i-retrieve-items-that-are-tagged-with-all-the-supplied-tags-in-linq/3479273#3479273 – 2010-08-22 02:04:48

回答

2

我相信你可以发现,在一个单一的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; 

这也没那么好。

+0

糟糕我的坏 - 我粘贴了错误的ICommand – 2010-08-21 23:41:30

+0

该查询引发此错误:'无法创建类型'标记'的常量值。只有原始类型('Int32,String和Guid')在此上下文中受支持。' – 2010-08-21 23:47:04

+0

它对我来说工作得很好,所以必须有一些关于你的代码的东西,你还没有告诉我们。例如,你确定'Tag.Id'的类型是'string'吗? – Timwi 2010-08-21 23:57:40

0

对于初学者,请参阅我的评论;无论如何,我怀疑查询是错误的!我会simplifiy它,通过简单地执行分开,每个标签存在:

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)); 
} 

这应该有强制规定的所有标签的净效应是当前和核算。

+0

嗨,可以你回答[这](http://forums.asp.net/t/2034468.aspx?Linq+Update+a+row+if+new+rows+are+inserted+in+another+table) – stom 2015-02-10 14:12:56

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)); 

我从数据库中读取我的注意收集,使用实体框架4.数据存储是我用它来管理我的自定义类EF4连接;它将EF4 ObjectContext作为属性保存。