2011-07-22 61 views
4

對於下面的查詢,我得到一個LINQ to SQL異常。搜索查詢給出了LINQ to SQL異常

var terms = "bob town".Split(' '); 
var q = from m in db.Monument 
    where terms.All(t => new List<string>() { 
     m.Name, 
     m.Street, 
     m.Owner }.Any(
      p => p.Contains(t))) 
    select m; 

唯一的例外是:

本地序列不能在LINQ被用來查詢 運營商除了包含運營商的SQL實現。

如何修改查詢以兼容LINQ to SQL?


目標

查詢的目標是這樣的。我有一個搜索條件列表和一個包含對象的數據庫。如果所有搜索條件都是至少一個屬性的子字符串,則應該返回一個對象。

例如。如果oo.name="creek mill"o.street="St. Petersroad",那麼搜索「mill petersroad」應該返回這個對象,但不應該搜索「mill foobar」。

+0

嘗試傑森的答案。 HTTP://計算器。com/questions/194930/how-do-i-use-linq-containsstring-instead-of-containsstring/195628#195628會不會解決你的問題? – naveen

+1

您可能在http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql有一些運氣 –

回答

0

下面是怎麼回事。我還沒有嘗試過,但它給你一個想法約

var terms = "bob town".Split(' '); 
     var q = from m in db.Monument 
       where m.Name.Split(' ').Intersect(terms).Count() > 0 || 
         m.Street.Split(' ').Intersect(terms).Count() > 0 
       select m; 

反正我覺得這種,你應該考慮使用SQL全文搜索,如果你有一個SQL數據庫搜索或」 .NET的Lucene 「這真的很適合你的情況下

+0

我們不想要精確的文本匹配,例如搜索「Petersroad」應該匹配「St. Petersroad」。此外,所有搜索字詞必須至少匹配一次。你可能會說這在LINQ中不可行。 – Matt

+0

我編輯了我的答案,它現在應該工作。 「相交」將返回兩個序列的任何交集:-) –

+0

我不確定這正是他想要的。這將返回包含條款的實體,但不包含包含* all *搜索條件的實體。 – InBetween

0

我敢肯定,可能有一種方法可以做到這一點與純LINQ,但我不知道如果它實際上是一個好主意:恕我直言,意見的人有時傾向於過度LINQ查詢除了LINQ非常酷,並沒有任何其他的原因,結束與查詢非常難只看他們。

爲什麼不實施擴展方法,需要Monument實體並計算出某個string[]是否符合您的標準?

這樣,你的LINQ表達無法獲得簡單:

var q = from m in db.Monument 
where m.ContainsAllSearchTerms(terms) 
select m; //readable and anyone understands right away what is going on here 

作爲ContainsAllSearchTerms(this Monument m, string[] terms)相關的擴展方法。

+0

你的建議是非常可讀的,但它仍然會被轉換爲SQL?循環遍歷C#中的所有實體可能會太慢。 – Matt

+0

我不確定這是否可以避免,無論你如何做。也許你應該看看Massimiliano提到的所有不同的選項(SQL全文搜索等)。我的建議是嘗試類似於我的建議,如果性能很差,那麼也許檢查其他方法。但我的建議是始終首先檢查最簡單的路徑。不成熟的優化通常是一個壞主意。 – InBetween

1

因此,實際的問題是Linq-To-SQL不知道如何將Linq的Terms部分轉換爲有效的SQL語句。所以,你必須重新調整查詢來幫助它。

我假設我們想使用Contains函數來獲取使用SQL IN運算符的SQL語句。這是我的建議。

var terms = "bob town".Split(' '); 
var q = from m in db.Monument 
    where 
      terms.Contains(m.Name) 
     || 
      terms.Contains(m.Street) 
     || 
      terms.Contains(m.Owner) 
    select m; 

我還沒有測試過,但它看起來應該可以工作,應該由Linq-To-SQL進行轉換。