【问题标题】:Entity framework: Include and Where clause in generic repository实体框架:通用存储库中的 Include 和 Where 子句
【发布时间】:2014-05-13 21:11:32
【问题描述】:

我正在使用实体框架(对象上下文)检查通用存储库的可能性。

我有一个界面

    interface IRepository<T> where T : class
    {
       IList<T> GetItems(Func<T, bool> Where, params string[] Navigations);
    }

以及实现接口的类

    class GenericRepository<T> : IRepository<T> where T : class
    {
       public IList<T> GetItems(Func<T, bool> Where, params string[] Navigations)
       {
           List<T> list;
           using(var ctx = new Context())
           {
               IQueryable<T> query = ctx.CreateObjectSet<T>();

               foreach (string nav in Navigations)
                    (query as ObjectQuery<O>).Include(nav);

               list = query.Where(Where).ToList<T>();
           }
           return list;
       } 
    }

然后我有另一个类扩展 GenericRepository。并实现另一个接口(现在不导入,因为该接口目前只是扩展了 IRepository 没有添加任何功能)。

    class EmployeeRepository : GenericRepository<Employee>, IEmployeeRepository
    {

    }

当我想从我的存储库中获取数据时,我会这样做:

    private void Test()
    {
        IEmployeeRepository rep = new EmployeeRepository();
        IList<Employee> list = rep.GetItems(
                                            e => e.Department.Name.Contains("Os")
                                            && e.Role.Type == 2,
                                            "Department", "Role"
                                           );
    }

在这里我收到一条错误消息,提示 e.Department 为空(我相信我在 Role 上也有一个)。

模型有三个实体

  • 员工
  • 部门
  • 角色

部门 1..* 员工 角色 1..1 员工

是否可以像我一样在参考表上添加预测? (有一些变化)。

谢谢!

【问题讨论】:

    标签: c# sql frameworks repository entity


    【解决方案1】:

    首先,使用Expression&lt;Func&lt;T, bool&gt;&gt; 而不是Func&lt;T, bool&gt;

    如果您使用Func&lt;T, bool&gt;,您将在应用谓词之前进行枚举!

    可能就够了。

    如果不是,请添加一些空检查。

    IList<Employee> list = rep.GetItems(
                                         e => e.Department != null && e.Department.Name.Contains("Os")
                                         && e.Role != null && e.Role.Type == 2,
                                         "Department", "Role"
                                        );
    

    最后,我将 GenericRepository 的实现更改为

    class GenericRepository<T> : IRepository<T> where T : class
        {
           public IList<T> GetItems(Expression<Func<T, bool>> predicate, params string[] navigationProperties)
           {
               List<T> list;
               using(var ctx = new Context())
               {
                   var query = ctx.Set<T>().AsQueryable();
    
                   foreach (string navigationProperty in navigationProperties)
                        query = query.Include(navigationProperty);//got to reaffect it.
    
                   list = query.Where(predicate).ToList<T>();
               }
               return list;
           } 
        }
    

    【讨论】:

    • 太棒了!谢谢。 Expression 因为它只包含在 DbContext 生成的上下文中,而不是 Object 上下文中。我将在下一个项目中尝试。非常感谢:)
    • 现在经过的时间也从 5000 毫秒下降到了 581 毫秒。由于我使用 where 发出查询,而不是加载到内存中然后过滤为 IEnumerable!
    • 确实更好 ;) 对于 Set,我认为 CreateObjectSet 并没有太大变化。但是无论如何都应该更正包含的部分。
    【解决方案2】:

    您确定所有员工都有一个部门吗?那个部门已经装满了? 否则我会添加一个检查 e.Department null

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-21
      相关资源
      最近更新 更多