2010-03-12 45 views
7

我想在LINQ生成這個SQL語句:LINQ到SQL IN /載有()爲空的<T>

select * from Foo where Value in (1, 2, 3) 

棘手位似乎是值是一列允許空值。

等效LINQ代碼似乎是:

IEnumerable<Foo> foos = MyDataContext.Foos; 
IEnumerable<int> values = GetMyValues(); 
var myFoos = from foo in foos 
      where values.Contains(foo.Value) 
      select foo; 

這當然不能編譯,因爲foo.Valueint?values鍵入到int

我已經試過這樣:

IEnumerable<Foo> foos = MyDataContext.Foos; 
IEnumerable<int> values = GetMyValues(); 
IEnumerable<int?> nullables = values.Select(value => new Nullable<int>(value)); 
var myFoos = from foo in foos 
      where nullables.Contains(foo.Value) 
      select foo; 

...這:

IEnumerable<Foo> foos = MyDataContext.Foos; 
IEnumerable<int> values = GetMyValues(); 
var myFoos = from foo in foos 
      where values.Contains(foo.Value.Value) 
      select foo; 

這兩個版本給我我所期望的結果,但他們不產生我想要的SQL 。看起來他們正在生成全表結果,然後對Contains()進行內存過濾(即:在普通的LINQ中,沒有-to-SQL); DataContext日誌中沒有IN子句。

有沒有辦法爲Nullable類型生成SQL IN?

注:

事實證明,我有沒有什麼可以做的問題包含或空的,所以我的問題的措辭基本上是無能爲力的。有關詳細信息,請參閱@Nick Craver接受的答案。

回答

14

這應該爲你工作,例如:

IEnumerable<int> values = GetMyValues(); 
var myFoos = from foo in MyDataContext.Foos; 
      where values.Contains(foo.Value.Value) 
      select foo; 

鑄造爲從一開始就IEnumerable<T>意味着執行將SQL外部的,而不是直接調用IQueryable<Foo>。如果您將其轉換爲IEnumerable並在查詢中使用它,則會獲得全部MyDataContext.Foos,然後使用該迭代器並在C#而不是SQL中執行查詢的其餘部分。

如果您想在SQL中運行,請不要將其轉換爲IEnumerable。效果與在查詢中使用MyDataContext.Foos.AsEnumerable()相同。

+0

哇,我沒有意識到,鑄造參考文件有所作爲(無疑是由於使用了特定類型的擴展方法)。從OOP的角度來看,這是不幸的。但是,它確實解決了我的問題。謝謝! –