0

I am using a entity framework wrapper for my project. It works fine if I use only one table for CRUD operation, but unfortunately I am not be able join two tables.

I have seen people are suggesting Include that also I am not be able to use.

reference

Also I have got this but I couldn't understand it.

I am sharing my BaseRepository class below

 public class BaseRepository<T> : IBaseRepository<T> where T : class
 {
    private IUnitOfWork unitOfWork;
    private DbSet<T> dbSet;

    public BaseRepository(IUnitOfWork unitOfWork)
    {
        this.unitOfWork = unitOfWork;
        this.dbSet = unitOfWork.DbContext.Set<T>();
    }

    public virtual IEnumerable<T> Get(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null, string includeProperties = "")
    {
        IQueryable<T> query = dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

    public virtual IEnumerable<T> Get()
    {
        return dbSet.ToList();
    }

    public virtual IEnumerable<T> Get(Expression<Func<T, bool>> predicate)
    {
        return dbSet.Where(predicate);
    }

    public virtual T Get(object id)
    {
        return dbSet.Find(id);
    }

    public virtual IQueryable<T> Where(Expression<Func<T, bool>> predicate)
    {
        return dbSet.Where(predicate);
    }

    public virtual IQueryable<T> Query()
    {
        return dbSet;
    }

    public bool Any(Expression<Func<T, bool>> predicate)
    {
        return dbSet.Any(predicate);
    }

    public T First(Expression<Func<T, bool>> predicate)
    {
        return dbSet.First(predicate);
    }

    public T FirstOrDefault(Expression<Func<T, bool>> predicate)
    {
        return dbSet.FirstOrDefault(predicate);
    }

    public virtual void Insert(T entity)
    {
        dbSet.Add(entity);
    }

    public virtual void Update(T entity)
    {

        if (unitOfWork.DbContext.Entry(entity).State == EntityState.Detached)
        {
            dbSet.Attach(entity);
        }

        unitOfWork.DbContext.Entry(entity).State = EntityState.Modified;
    }

    public virtual void Delete(object id)
    {
        T entityToDelete = dbSet.Find(id);
        Delete(entityToDelete);
    }

    public virtual void Delete(T entity)
    {
        if (unitOfWork.DbContext.Entry(entity).State == EntityState.Detached)
        {
            dbSet.Attach(entity);
        }
        dbSet.Remove(entity);
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                unitOfWork.DbContext.Dispose();
            }
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    public IEnumerable<T> ExecWithStoreProcedure(string query, params object[] parameters)
    {
        return unitOfWork.DbContext.Database.SqlQuery<T>(query, parameters);
    }
}

Please let me know what changes I need to perform in my BaseRepository so that I can perform join.

Community
  • 1
  • 1
  • 1
    What do you don't understand? – CodeNotFound Nov 14 '15 at 19:38
  • I didn't understand how to encapsulate a complex query.I want to use like var empList = (from e in empRepository.Where(e => e.EmpID==123) join d in deptRepository on e.DeptID equals d.DeptID – Liakat Ali Mondol Nov 14 '15 at 20:13
  • I removed the repository pattern references from your question as you have not understood the purpose of the pattern (being an abstraction over the persistence layer to reduce complexity). Any class exposing LINQ (just wrapping Linq To Sql) is not an abstraction at all. You still have to know the limitations of your ORM to use it. Can you please describe what benefits your solution give you over using the EF interfaces directly? I just don't see it. The accepted answer looks exactly like using EF directly and clearly illustrates my point. – jgauffin Nov 17 '15 at 19:46

1 Answers1

1

Alright...So, looking at your base repository it looks like you have things in place. My best guess is you are just getting confused using the repository pattern. So, you showed us the BaseRepository that takes type <T>. How is your specific repository created? eg you must be having, say, AccountRepository or ContactRepository which need to make use of the generic base repository something like this in your UnitOfWork class:

private IBaseRepository<Account> _accountRepository;    
    public IBaseRepository<Account> AccountRepository
    {
        get { return _accountRepository ?? (_accountRepository = new BaseRepository<Account>(_databaseFactory)); }
    }

which you can invoke as below:

private IBaseRepository<Account> accountRepo { get { return UnitOfWork.AccountRepository; } }

and use it like accountRepo.Get() which will give you list of all the Accounts.

If this is how you are using your repositories then all you need to do for joins is add the repository of the other entity:

private IBaseRepository<Contact> contactRepo { get { return UnitOfWork.ContactRepository; } }

and perform join the as below:

return (from c in contactRepo.GetAll()
            join a in accountRepo.GetAll() on c.AccountId equals a.AccountId
            where a.Name == "Test Account Name"
            select c).ToList();

The above will give you all the contacts that belong to the account with Name = "Test Account Name".

Let me know how did it work for you.

Mr Lister
  • 45,515
  • 15
  • 108
  • 150
Manish Kumar
  • 362
  • 1
  • 9
  • @Manish Kumar `GetAll()` How is this function define ?, My concern will the `GetAll()` will return the entire table to memory . In the above repository pattern `Get()` with `includeProperties` will result in `inner join` – Eldho Nov 19 '15 at 10:01
  • @Eldho that is a valid concern but the above suggestion doesnt suffer from the performance issue that you dread of. Because, in Repository pattern, GetAll() should be implemented as below: public virtual IQueryable GetAll() {return _dbset;} Notice return type IQueryable which will NOT evaluate the query, it will create "Queryable" query that will exec ONLY after .ToList(): return (from c in contactRepo.GetAll() join a in accountRepo.GetAll() on c.AccountId equals a.Id where a.Id == 1 select c).ToList(); Due to where condition before .ToList() only matching records are loaded in memory. – Manish Kumar Nov 19 '15 at 14:51
  • Thanks manish, i didnt noticed it was iQuerable . Thanks for your detailed information , appreciate it – Eldho Nov 19 '15 at 15:02