【问题标题】:LINQ query with a WHERE clause with multiple conditions带有多个条件的 WHERE 子句的 LINQ 查询
【发布时间】:2012-04-26 21:40:08
【问题描述】:

我将 EntityFramework 与 POCO 一起使用。
假设我有这样定义的 POCO(简化):

class Class1
{
    public int ID;
    public int SomeNumber;
}

class Class2
{
    public int ID;
    public int SomeNumber;
}

class Class3
{
    public int ID;
    public int SomeNumber;
}

class SomeClass
{
    public int ID;
    public int? Class1ID;
    public Class1 Class1;
    public int? Class2ID;
    public Class2 Class2;
    public int? Class3ID;
    public Class3 Class3;
}

我想从数据库中获取所有SomeClass 记录,这些记录属于Class1Class2Class3 其中ClassX.SomeNumber 等于某个数字。

我编写了如下所示的 LINQ 查询:

Database DB = new Database(); // object context
var result = DB.SomeClass.ToList();

int SomeNumber = 1; // some number
List<SomeClass> retValue = result
    .Where(x =>
        {
            int Number = 0;
            if (x.Class1 != null)
                Number = x.Class1.SomeNumber;
            else if (x.Class2 != null)
                Number = x.Class2.SomeNumber;
            else if (x.Class3 != null)
                Number = x.Class3.SomeNumber;
            return Number == SomeNumber;
        })
    .ToList();

...但是retValue 不包含任何记录。

解决方案

显然我必须指定 .Include 语句,因为延迟加载已禁用,x.Class1x.Class2x.Class3 始终具有 null 值。我感到很惭愧,因为我没有明确声明延迟加载已被禁用——那时问题就很明显了。

不过多亏了 Ladislav 的帖子,我改进了我的代码,如下所示:

Database DB = new Database(); // object context

int SomeNumber = 1; // some number
List<SomeClass> retValue = DB.SomeClass
    .Include("Class1")
    .Include("Class2")
    .Include("Class3")
    .Where(x =>
        SomeNumber == x.Class1.SomeNumber ||
        SomeNumber == x.Class2.SomeNumber ||
        SomeNumber == x.Class3.SomeNumber)
    .ToList();

我不知道 LINQ-to-Entities 应该执行自动空值合并。

【问题讨论】:

    标签: linq entity-framework


    【解决方案1】:

    恕我直言,您应该没问题:

    Database DB = new Database(); 
    var result = DB.SomeClass.Where(x =>
                                Number == x.Class1.SomeNumber ||
                                Number == x.Class2.SomeNumber ||
                                Number == x.Class3.SomeNumber)
                             .ToList();
    

    您的查询会加载所有数据,然后在 .NET 中评估条件 = 您必须在访问 SomeNumber 之前测试空值,但如果您通过 Linq-to-entities 在 SQL 中评估 SomeNumber,则不需要这样做。 Linq-to-entities 应该执行自动空值合并。

    【讨论】:

    • 实际上解决方案是(我通常在我询问后不久自己发现)由于延迟加载禁用,我必须在运行 Where 子句之前执行 var result = DB.SomeClass.Include("Class1").Include("Class2").Include("Class3")。但是我将其标记为已接受,因为您教我如何改进我的代码(直接在 LINQ-To-Entities 中使用 Where
    【解决方案2】:

    根据你的逻辑,如果 x.Class1 不为 null,但 x.Class1.SomeNumber 为 3,则不会检查所有其他子句。

    如果你想检查,如果只是一些ClassN.SomeNumber == SomeNumber,那么你应该这样做:

    int SomeNumber = 1; // some number 
    List<SomeClass> retValue = result 
        .Where(x => 
            { 
                if (x.Class1 != null && x.Class1.SomeNumber == SomeNumber) 
                    return true;
                else if (x.Class2 != null && x.Class2.SomeNumber == SomeNumber) 
                    return true;
                else if (x.Class3 != null && x.Class3.SomeNumber == SomeNumber) 
                    return true;
                return false;
            }) 
        .ToList();
    

    【讨论】:

    • 这段代码是不是和我用的一样,只是我的代码多了1行?
    • 否,因为如果数字相等,它会立即返回。在您的代码中,可能有一个正确的数字,但它会被另一个 if 子句覆盖。
    • 它不能被覆盖,因为有else子句,如果没有条件匹配则返回0。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多