LINQ-to-SQL IN/Contains()用于Nullable <T>

Cra*_*ker 9 sql linq nullable linq-to-sql

我想在LINQ中生成这个SQL语句:

select * from Foo where Value in ( 1, 2, 3 )
Run Code Online (Sandbox Code Playgroud)

棘手的一点似乎是Value是一个允许空值的列.

等效的LINQ代码似乎是:

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

当然,这不会编译,因为它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;
Run Code Online (Sandbox Code Playgroud)

...还有这个:

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

这两个版本都给了我期望的结果,但它们不会生成我想要的SQL.它们似乎正在生成全表结果,然后在内存中进行Contains()过滤(即:在普通LINQ中,没有-to-SQL); INDataContext日志中没有子句.

有没有办法为Nullable类型生成SQL IN?

注意

事实证明,我遇到的问题没有任何关系包含或Nullable,所以我的问题的措辞在很大程度上是无关紧要的.有关详细信息,请参阅@Nick Craver接受的答案.

Nic*_*ver 15

这适用于您的示例:

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

铸造作为IEnumerable<T>从一开始就意味着执行将SQL外部,而不是调用IQueryable<Foo>直接.如果你IEnumerable在查询中强制转换并使用它,那么它将MyDataContext.Foos使用该迭代器并在C#中而不是在SQL中执行查询的其余部分.

如果您想在SQL中运行,请不要在IEnumerable任何地方进行转换.效果与MyDataContext.Foos.AsEnumerable()在查询中使用的效果相同.

  • 哇,我没有意识到转换引用会产生影响(无疑是由于使用了特定类型的扩展方法)。从 OOP 的角度来看,这是不幸的。不过,它确实解决了我的问题。谢谢! (2认同)