I'm checking out possibilities with a generic repository using Entity framework (object context).

I have an interface

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

And the class implementing the interface

    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;
       } 
    }

Then I have another class extending GenericRepository. And implementing another interface(not import right now since that interface currently just extends IRepository with no features added).

    class EmployeeRepository : GenericRepository<Employee>, IEmployeeRepository
    {

    }

When I want to fetch data from my repository I do something like this:

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

And here I get an error saying e.Department is null (I believe I get one on Role as well).

The model has three entities

  • Employee
  • Department
  • Role

Department 1..* Employee Role 1..1 Employee

Is it possible to add predictions on references tables like I do? (with some changes).

Thanks!

有帮助吗?

解决方案

First, use Expression<Func<T, bool>> instead of Func<T, bool>.

If you use Func<T, bool>, you will enumerate before applying your predicate !

It may be enough.

If it's not, add some null checks.

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

Finally, I would change the implementation of GenericRepository to

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;
       } 
    }

其他提示

You are sure that all employees have a department? And that that department is loaded? otherwise i would add a check if e.Department <> null

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top