代码之家  ›  专栏  ›  技术社区  ›  Craig Walker

linq to sql in/contains()for nullable<t>

  •  8
  • Craig Walker  · 技术社区  · 16 年前

    我想在LINQ中生成此SQL语句:

    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.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);没有 IN DataContext日志中的子句。

    是否有方法为可为空类型生成SQL-In?

    注释

    事实证明,我遇到的问题与contains或nullable没有任何关系,因此我问题的措词在很大程度上是不相关的。详情请参见@nick craver's accepted answer。

    1 回复  |  直到 16 年前
        1
  •  14
  •   Nick Craver    16 年前

    这应该适用于您的示例:

    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中运行,请不要强制转换为 可枚举的 一路上的任何地方。效果与使用相同 MyDataContext.Foos.AsEnumerable() 在查询中。