none
Entity framework repository class in DAL returning IQueryable? RRS feed

  • Question

  • Hi,

    I've got a Silverlight client, WCF service and a SQL DB. In the WCF service I have a business logic layer and a data access layer. I'm using the entity framework. I've put in a generic repository class in the DAL using some of the examples I've seen on the web. They all seem to return IQueryable<T> etc. So for example in my DAL i may have 

    public IQueryable<T> GetList<T>() .................

    I call this from my BLL, eg List<Something> list = DAL.GetList<Something>().ToList().

    I've noticed that the data doesn't come back after the call to the DAL, but when the ToList() executes. I understand this is because the connection is not yet open and the EF is managing the connection and opens it only when necessary. However, if the database is down etc, I then get the connectivity exceptions thrown by the ToList() call and I'm having to catch them in the BLL. I want my DAL to control the data access and any exceptions relating to it, not my BLL. 

    So I thought I could change my DAL to return List<T> etc and ensure it actually tried to get the data before going back to the BLL. That way any data connectivity issues are caught and handled in the DAL. 

    In the BLL if I need to filter and data etc, I can just use LINQ on my list etc. I know I must be missing something as all the examples are returning IQueryable.

    I'm new to EF and maybe I'm looking at this wrong?

    So the question is why return IQueryable from DAL instead of List<T>?

    Thanks for any help!

    Thursday, May 24, 2012 3:06 PM

Answers

  • Hi rockshire,

    Linq support deferred execution for some operators, so a lambda expression for example get compiled after been declared, but executes only when you execute the expression (e.g start to iterate it), in fact your .ToList() in BLL forces the query to execute, if you want that your DAL execute query without calling ToList() in your BLL you can put a to ToList() call in the DAL's generic repository methods, for being able to filter in the DAL without loading all data from dB and filter it in memory, you have to create a generic repository with filter capabilities, i'll show a simple Find method example:

    public interface IRepository<T> where T : class
    {
        IEnumerable<T> GetAll();
        IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
     
        void Delete(T entity);
        void Add(T entity);
        void Attach(T entity);
    }
    
    public class Repository<T> : IRepository<T> where T : class
    {
       IObjectSet<T> _objectSet;
     
       public Repository(IObjectContext objectContext)
       {
           _objectSet = objectContext.CreateObjectSet<T>();
       }
     
       public IEnumerable<T> GetAll()
       {
           return _objectSet.ToList();
       }
     
       public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
       {
           return _objectSet.Where(predicate).ToList();
       }
     
       public void Delete(T entity)
       {
           _objectSet.DeleteObject(entity);
       }
     
       public void Add(T entity)
       {
           _objectSet.AddObject(entity);
       }
     
       public void Attach(T entity)
       {
           _objectSet.Attach(entity);
       }
    }

    Usage example:

    var customerRepo = new Repository<Customer>(context);
    var johnCustomer = customerRepo.Find(c => c.Name == "John").SingleOrDefault();

    Hope it helps.

    Max



    Thursday, May 24, 2012 7:35 PM

All replies

  • Hi rockshire,

    Linq support deferred execution for some operators, so a lambda expression for example get compiled after been declared, but executes only when you execute the expression (e.g start to iterate it), in fact your .ToList() in BLL forces the query to execute, if you want that your DAL execute query without calling ToList() in your BLL you can put a to ToList() call in the DAL's generic repository methods, for being able to filter in the DAL without loading all data from dB and filter it in memory, you have to create a generic repository with filter capabilities, i'll show a simple Find method example:

    public interface IRepository<T> where T : class
    {
        IEnumerable<T> GetAll();
        IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
     
        void Delete(T entity);
        void Add(T entity);
        void Attach(T entity);
    }
    
    public class Repository<T> : IRepository<T> where T : class
    {
       IObjectSet<T> _objectSet;
     
       public Repository(IObjectContext objectContext)
       {
           _objectSet = objectContext.CreateObjectSet<T>();
       }
     
       public IEnumerable<T> GetAll()
       {
           return _objectSet.ToList();
       }
     
       public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
       {
           return _objectSet.Where(predicate).ToList();
       }
     
       public void Delete(T entity)
       {
           _objectSet.DeleteObject(entity);
       }
     
       public void Add(T entity)
       {
           _objectSet.AddObject(entity);
       }
     
       public void Attach(T entity)
       {
           _objectSet.Attach(entity);
       }
    }

    Usage example:

    var customerRepo = new Repository<Customer>(context);
    var johnCustomer = customerRepo.Find(c => c.Name == "John").SingleOrDefault();

    Hope it helps.

    Max



    Thursday, May 24, 2012 7:35 PM
  • Hi iL.MaX,

    Thanks for the reply. The example all makes sense and has answered my question.

    Cheers!

    Thursday, May 24, 2012 8:12 PM