我想在LINQ中生成这个SQL语句:
select * from Foo where Value in ( 1, 2, 3 )
棘手的一点似乎是Value是一个允许空值的列。
等效的LINQ代码似乎是:
IEnumerable<Foo> foos = MyDataContext.Foos;
IEnumerable<int> values = GetMyValues();
var myFoos = from foo in foos
where values.Contains(foo.Value)
select foo;
当然,这不会编译,因为foo.Value
是int?
而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?
事实证明,我遇到的问题没有任何关系包含或Nullable,所以我的问题的措辞在很大程度上是无关紧要的。有关详细信息,请参阅@Nick Craver接受的答案。
答案 0 :(得分: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()
相同。