5

I have this repository,

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private readonly DbContext context;
    private readonly DbSet<TEntity> dbEntitySet;

    public Repository(DbContext context)
    {
        if (context == null)
            throw new ArgumentNullException("context");

        this.context = context;
        this.dbEntitySet = context.Set<TEntity>();
    }

    public IEnumerable<TEntity> GetAll()
    {
        return this.dbEntitySet;
    }

    public IEnumerable<TEntity> GetAll(string include)
    {
        return this.dbEntitySet.Include(include);
    }

    public IEnumerable<TEntity> GetAll(string[] includes)
    {
        foreach (var include in includes)
            this.dbEntitySet.Include(include);

        return this.dbEntitySet;
    }

    public void Create(TEntity model)
    {
        this.dbEntitySet.Add(model);
    }

    public void Update(TEntity model)
    {
        this.context.Entry<TEntity>(model).State = EntityState.Modified;
    }

    public void Remove(TEntity model)
    {
        this.context.Entry<TEntity>(model).State = EntityState.Deleted;
    }

    public void Dispose()
    {
        this.context.Dispose();
    }
}

and the issue I have is with this method:

public IEnumerable<TEntity> GetAll(string[] includes)
{
    foreach (var include in includes)
        this.dbEntitySet.Include(include);

    return this.dbEntitySet;
}

When I run it and put a breakpoint before the return, it is as if the foreach is being ignored.

the method above it works fine:

public IEnumerable<TEntity> GetAll(string include)
{
    return this.dbEntitySet.Include(include);
}

To call it, I basically do this:

var a = this.Repository.GetAll(new string[] { "ForbiddenUsers", "ForbiddenGroups" }).ToList();

which pulls back the results but not does include the includes :D If I modify the call to:

var a = this.Repository.GetAll("ForbiddenUsers").ToList();

It works fine.

Can someone provide me with a resolution?

rae1
  • 6,066
  • 4
  • 27
  • 48
r3plica
  • 13,017
  • 23
  • 128
  • 290

2 Answers2

9

Change your method to look like this:

public IEnumerable<TEntity> GetAll(string[] includes)
{
    var query = this.dbEntitySet;

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

    return query;
}

The Include method does not mutate the DbSet, it only returns you a new DbQuery with your include.

luksan
  • 7,661
  • 3
  • 36
  • 38
  • For the first one, I get an invalid cast exception, for the second one it errors out when I run it (it compiles fine). I am going to do a few more tests to see what the problem is – r3plica Jan 16 '14 at 10:21
  • Yeah, the problem with your second method is that you the include thinks I am trying to create a navigation property with all the joined strings which just doesn't work – r3plica Jan 16 '14 at 10:25
  • Ah, OK. I thought you might be able to do that but I guess I was mistaken. I've removed that second example. – luksan Jan 16 '14 at 15:57
1

This code is incorrect:

public IEnumerable<TEntity> GetAll(string[] includes)
{
    foreach (var include in includes)
       this.dbEntitySet.Include(include);

    return this.dbEntitySet;
}

The correct code is the following:

public IEnumerable<TEntity> GetAll(string[] includes)
{
     IQueryable<T> query = this.dbEntitySet;

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

    return query;
}

In your place I will use Lambda Expressions like this:

public IEnumerable<TEntity> GetAll(Expression<Func<T, object>>[] includes)
{
     IQueryable<T> query = this.dbEntitySet;

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

     return query;
}
CodeNotFound
  • 22,153
  • 10
  • 68
  • 69
  • Lambdas may not work here. `Expression>` is not convertible to `Expression>`, and I believe a cast in the lambda will throw off the magic. – Cory Nelson Jan 15 '14 at 16:43
  • @CoryNelson I never mentionned Expression>. Expression> work well for me. Where did you see that TRet in my code? – CodeNotFound Jan 15 '14 at 17:11
  • Indeed you did not mention it -- what I'm pointing out is that everyone's lambdas *will* be of some type -- not `object` -- so I don't see the usefulness of your method as expressions for `Func` etc. are not convertible to expressions for `Func`. – Cory Nelson Jan 15 '14 at 18:52
  • Did you test my code before talking about that? Maybe it's not work with your scenarios but it works well for me. You can check this example => http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx – CodeNotFound Jan 15 '14 at 19:24
  • @CodeNotFound your first query has the same problem as mine. It seems to ignore the includes, although it does compile. Also, how would you call the second method?? – r3plica Jan 16 '14 at 10:40
  • @r3plica If you read my post i said that the firt query is incorrect. The second is the correct. Not forget to use my last query beacuase it uses lambda expressions. – CodeNotFound Jan 16 '14 at 17:00
  • Hey @CodeNotFound Your second query is incorrect too, it should be query = query.Include(include); – r3plica Jan 18 '14 at 00:14