【问题标题】:Entity Framework eager loading based on a specific attribute基于特定属性的实体框架预加载
【发布时间】:2018-02-20 22:22:08
【问题描述】:

我的应用程序中当前的 EF 设置是延迟加载,这在大多数情况下都很棒。但是,我在尝试如何根据 IsEnabled 位属性加载相关实体列表时迷失了方向。

在这个例子中,我只是返回一个实体列表。

return Context.Entities.ToList()

假设Entities 对象包含ChildEntities 的列表,如下所示:

public class Entities
{        
    private string EntityName;

    private List<ChildEntities> ChildEntities;
}

public class ChildEntites
{        
    private string ChildEntityName;
    private bool IsEnabled;
}

我只想在加载Entities 列表时根据他们的IsEnabled 标志取出ChildEntities

【问题讨论】:

  • 我认为使用Include() 进行急切加载是不可能的,但也许延迟加载的Context.Entities.Where(e =&gt; e.IsEnabled).ToList() 足够快?这应该在任何对象物化之前在数据库上运行。
  • 无法使用急切加载(Include),因为它不支持过滤,Include总是加载整个集合

标签: c# entity-framework


【解决方案1】:

您可以使用Include() 方法加载所有子实体,然后只选择那些已启用的实体

Context.Entities.Include("ChildEntites").Select(c => e.IsEnabled == true)

另一种方法是获取过滤器实体,然后按照in this post 所示运行查询

var data = from e in Context.Entities
            select new
            {
                Entities = e,
                Childs = e.ChildEntites.Where(c => c.IsEnabled == true) 
            };

var Results = data.ToArray().Select(x => x.Entities);

【讨论】:

    【解决方案2】:

    我认为当你加载相关实体时没有办法过滤,以防你使用延迟加载或急切加载,除非你将查询投影到匿名类型或DTO,但如果你有一个实体实例,你可以使用显式加载根据条件加载相关实体:

    var entity=context.Entities.FirstOrDefault();
    context.Entry(entity) 
            .Collection(b => b.ChildEntities) 
            .Query() 
            .Where(ce => ce.IsEnabled == true) 
            .Load(); 
    

    如果由于需要加载整个实体集合而不能满足您想要实现的目标,那么,正如我之前所说,您应该将查询投影到自定义类或匿名类型:

     var query= from e in Context.Entities.Include(c=>c.ChildEntities)
                select new EntityDTO
                {
                    EntityName= e.EntityName,
                    ChildEntites= e.ChildEntites.Where(c => c.IsEnabled == true) 
                };
    

    【讨论】:

      【解决方案3】:

      使用投影

      var entities = context.Entities
                            .Select(x => new {x, x.ChildEntities.Where(y => y.IsEnabled))
                            .ToList() // resolve from database before selecting the main entity
                            .Select(x => x.x);
      

      使用第三方库

      EF+ Query IncludeFilter 让您轻松过滤相关实体

      var entities = context.Entities.IncludeFilter(x => x.ChildEntities.Where(y => y.IsEnabled))
                                     .ToList();
      

      您可以找到文档here

      免责声明:我是项目的所有者EF+

      【讨论】:

        【解决方案4】:

        我会推荐这种方法的几种方法。我要么在 IsEnabled = false 的地方延迟加载,要么在 IsEnabled = true 的单独调用中急切加载,或者一旦你拥有延迟加载的集合,在单独的调用中,获取 IsEnabled = true 的孩子。我不相信你能在一个电话中做到这一点。另一种选择是存储过程。我希望这会有所帮助。

        【讨论】:

          【解决方案5】:

          我遇到了类似的问题。我通过以下方式解决了。

          在您的模型实体中创建一个新方法。让我们称之为 ChildEntitiesEnabled

           public ICollection<ChildEntity> ChildEntitiesEnabled()
           {
                //First I get the full list using the lazy loading...
                var allChildEntities=ChildEntities.ToList();
          
                //do further processing if there is data
                if(allChildEntities!=null && allChildEntities.Count()>0)
                {
          
                   var childEntitiesEnabled =  ChildEntities.Where(x=>x.Enabled==true).ToList();
          
                   return childEntitiesEnabled;
                }
          
                return null; //or you can return an empty list...
           }
          

          我喜欢这种方法,因为您可以在模型可用的任何地方使用它,而无需到处散布复杂的代码。此外,您不会丢失所有 ChildEntities 数据...这也可从原始调用中获得。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-03-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-10-11
            相关资源
            最近更新 更多