Danijel Boksan Danijel Boksan - 3 years ago 108
C# Question

EF Generic Repository Multiple Includes

Idea is to have one Generic Repository which will work with all entities.
I managed that, but if I need to have method which should include one or more other entities there is a problem for me.
I have put some idea in code, but that is not working for me.
Also I have been thinking to use aggregate function in EF, but that I have never use. Can someone give me direction how I can manage this ?

public interface IRepository<T> where T : BaseEntity
{
IEnumerable<T> GetAll();
T Get(Int64 id);
void Insert(T entity);
void Delete(T entity);
Task<bool> SaveChangesAsync();
T SearchByName(Expression<Func<T, bool>> predicate);
IEnumerable<T> GetAll(string[] includes);

}



public class Repository<T> : IRepository<T> where T : BaseEntity
{
private Entities.AppContext _context;
private DbSet<T> entities;

public Repository(Entities.AppContext context)
{
_context = context;
entities = _context.Set<T>();
}

public void Delete(T entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
entities.Remove(entity);
}

public T Get(long id)
{
return entities.SingleOrDefault(s => s.Id == id);
}

public IEnumerable<T> GetAll()
{
return entities.ToList();
}

public IEnumerable<T> GetAll(string[] includes)
{
foreach (string include in includes)
{
entities.Include(include);
}
return entities;
}

public void Insert(T entity)
{
if (entity == null)
{
throw new ArgumentNullException("entity");
}
entities.Add(entity);
}

public async Task<bool> SaveChangesAsync()
{
try
{
return (await _context.SaveChangesAsync()) > 0;
}
catch (Exception ex)
{

return false;
}

}

public T SearchByName(Expression<Func<T, bool>> predicate)
{
return entities.Where(predicate).SingleOrDefault();
}
}

Answer Source

You have fallen in the typical trap of calling a method which returns something and ignoring the result. The line entities.Include(include); does nothing - similar to entities.Where(...);, entities.Select(...); etc.

The correct code is something like this:

var query = entities.AsQueryable();
foreach (var include in includes)
    query = query.Include(include);
return query;

or with single line Aggregate:

return includes.Aggregate(entities.AsQueryable(), (query, path) => query.Include(path));
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download