2010-08-21 90 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作爲屬性保存。