代码之家  ›  专栏  ›  技术社区  ›  Collin Barrett

EF-Core不必要地执行条件赋值逻辑的两个分支

  •  1
  • Collin Barrett  · 技术社区  · 6 年前

    我遇到了一个EF Core的问题,如果我用分支逻辑分配一个属性,两个分支都会执行(而不仅仅是condition==true的分支)。

    在下面的第一个代码示例中,我将实际尝试测试的条件替换为一个我知道始终为false的条件,以验证我的问题。在我的现实世界的例子中 MyEntities 映射到没有具有 Id

    然而,当我调用这个方法时,我可以在输出窗口中首先看到要获取where的查询 身份证件 是1000(不返回结果),然后 N 尝试检索 Count 不应该执行(另一个) (int?)null 分支只能执行),对吗?

    我怀疑这可能是EF-Core或我的EF-Core提供者(pomelomysql)的一个bug,但我想确保我没有误解LINQ中EF和/或分支的工作方式。两个分支都不应该以有条件的方式执行,对吗?如果你认为这可能是一个错误,我怎么知道它是与EF核心还是我正在使用的供应商?

    public async Task<IEnumerable<MyEntityDto>> GetMyEntityDtosAsync() =>
        await DbContext.MyEntities
                       .Select(l => new MyEntityDto
                       {
                           Id = l.Id,
                           RuleCount = l.Id == 1000  // known to always be false
                               ? l.MyLinkedEntity
                                  .Where(s => s.MyBoolean)
                                  .FirstOrDefault()
                                  .MyManyToMany
                                  .Count
                               : (int?)null
                       });
    

    我试图实现的实际查询看起来更像下面这样,以便在每个 MyEntity 没有 MyLinkedEntity MyBoolean == true . 这在没有任何异常的情况下抛出异常 s满足这些条件(应该由条件处理)。我是否可以尝试一种变通逻辑?

    public async Task<IEnumerable<MyEntityDto>> GetMyEntityDtosAsync() =>
        await DbContext.MyEntities
                       .Select(l => new MyEntityDto
                       {
                           Id = l.Id,
                           RuleCount = l.MyLinkedEntity.Any(s => s.MyBoolean)
                               ? l.MyLinkedEntity
                                  .Where(s => s.MyBoolean)
                                  .FirstOrDefault()
                                  .MyManyToMany
                                  .Count
                               : (int?)null
                       });
    

    更新: 添加POCO

    public class MyEntity {
        public int Id { get; set; }
        public int MyLinkedEntityId { get; set; }
        public MyLinkedEntity MyLinkedEntity { get; set; }
        ...
    }
    
    public class MyLinkedEntity {
        public int Id { get; set; }
        public bool MyBoolean { get; set; }
        ...
    }
    
    public class MyManyToMany {
        public int MyLinkedEntityId { get; set; }
        public MyLinkedEntity MyLinkedEntity { get; set; }
        public int MyOtherLinkedEntity { get; set; }
        public MyOtherLinkedEntity MyOtherLinkedEntity { get; set; }
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   Moho    6 年前

    我的猜测是:EF正在检索所有可能是最终投影的一部分的数据,然后用结果评估您的条件逻辑客户端。

    你得到的错误是由于你引用了 MyLinkedEntity.MyManyToMany.Count FirstOrDefault() .

    既然你还没有发布poco,我就给你添加了poco,但是要处理一组poco类型的实体 l.MyLinkedEntity 在当前代码中,按主体(从中投影的实体)和项目分组 ManyToMany.Count 之前 打电话 . 希望这能起作用,我不在家测试:P

    DbContext.MyLinkedEntities
        .GroupBy( mle => mle.MyEntity )
        .Select( g => new
        {
            Id = g.Key.Id,
            RuleCount = g.Where( s => s.MyBoolean )
                .Select( s => ( int? )s.ManyToMany.Count )
                .FirstOrDefault()
        }