2010-07-28 22 views
3

我正在使用ASP.NET MVC應用程序,它使用存儲庫模式LINQ to SQL作爲我的數據源。說在LINQ to SQL'Lambda表達式怪異'條件

public IEnumerable<T> Find(Expression<Func<T, bool>> where) 
{ 
    return _context.GetTable<T>().Where(where); 
} 

我能夠把這個:在我的倉庫我露出下面的方法

repository<User>().Find(u => true); 

但如果我嘗試做的(當搜索爲null)

repository<User>().Find(u => !string.IsNullOrEmpty(search) ? u.UserName.Contains(search) : true); 

我收到錯誤:

Value cannot be null. Parameter name: text

I t因爲搜索的值爲null,所以要求lambda表達式執行相同的事情,但顯然不是這種情況。

我該如何解決這個問題?

+0

你可以展示更多的上下文嗎?懶惰的評估使得LINQ很難分析,而不會看到你如何使用它的輸出。 – 2010-07-28 13:13:39

+0

IsNullOrEmpty's和Contains的參數被稱爲'value',所以錯誤不是來自它們。 – SWeko 2010-07-28 13:14:59

+1

@SWeko:'string.Contains'不會拋出異常,表達式解析器對'string.Contains'調用的評估來構造一個'LIKE'表達式。 – 2010-07-28 13:17:51

回答

1

要添加到其他的答案,如果你遵循這個理想,你可以簡單地這樣做,而不是:

repository<User>.Find(u => string.IsNullOrEmpty(search) || 
          u.UserName.Contains(search)); 

之前盲目執行此,如果你這樣做,請閱讀亞當回答瞭解後果。

+0

感謝這個解決方案的工作。 – nfplee 2010-07-28 14:53:10

+0

我剛剛發現如果我說: 知識庫。查找(u =>(string.IsNullOrEmpty(search)|| u.UserName.Contains(search))&&(!enabled.HasValue || u.Enabled = = enabled.Value)); 我遇到了和以前一樣的問題。格兒 – nfplee 2010-08-02 10:55:03

1

包含需要一個字符串。你應該通過string.Emtpy

u.UserName.Contains(search) 

如果你試試這個,它會編譯,但你會得到一個運行時錯誤:

string str = "Leniel"; 

if (str.Contains(null)) 
{ 
    var num = 1; 
} 

錯誤:

Value cannot be null. 
Parameter name: value 
+1

'string.Contains'沒有被調用。表達式中對'string.Contains'的調用被轉換爲SQL中的LIKE表達式。這種翻譯是拋出異常的東西。請注意參數名稱的不同(「值」與「'文本') – 2010-07-28 13:20:06

3

因爲這是一種表達,正常條件運算符邏輯(不評估錯誤表達)不會自動應用。由於該表達式實際上正被翻譯成SQL查詢表達式,因此LINQ to SQL正在評估該條件的參數,在這種情況下,它是null。雖然LIKE null是有效的SQL語法,但顯然LINQ to SQL不讚賞被傳遞null。您必須構造兩個不同的查詢,一個用於空項,一個用於非空項。

要麼是這樣,要麼通過string.EmptyContains。這裏唯一的影響是無法在列上使用索引,因爲服務器將對每一行進行重複的條件評估,強制進行表掃描。我建議使用兩個沒有條件的查詢。