1

I at this moment I have repository filled with multiple gets methods.

E.q. Get1() => cxt.Entites.Include(e => e.obj1); Get2() => cxt.Entities.Include(e => e.obj1).Include(e => e.obj2)

And so on.

Is there good method, pattern to have one GET method where I can send inclues via parameter?

Nerf
  • 938
  • 1
  • 13
  • 30

2 Answers2

1

I did the following in my projects:

public Entity[] GetAll(bool includeObj1, bool includeAllOthers) {
    IQueryable<Entity> entity = ctx.Entities;

    if (includeObj1) 
        entity = entity.Include(e => e.obj1);

    if (includeAllOthers) {
        entity = entity
            .Include(e => e.obj2)
            .Include(e => e.obj3)
            .Include(e => e.obj4)
            .Include(e => e.obj5);
    }

    return entity.ToArray();
}

Providing arguments like includeObj1 and includeObj2 separates a consumer of repository from implementation and encapsulates any data access logic.
Passing direct "include these properties" orders to a repository means that you know how repository works and assume that it is some sort ORM which blurs abstractions.

Yeldar Kurmangaliyev
  • 33,467
  • 12
  • 59
  • 101
  • Nah, it's not good. I have many objects to include. So I don't want method with 7+ arguments. – Nerf May 31 '17 at 09:11
  • @Nerf Better than having 7+ methods with similar contents. If you need a method which returns different results according to 7 possible state options, then it is expectable to have 7 arguments. – Yeldar Kurmangaliyev May 31 '17 at 09:15
1
public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<TEntity> 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();
        }
    }

See repository pattern in msdn You can use

_sampleRepostiory.Get(h=>h.Id>1,null,"Employees.Departments");

Including same with lambda

public virtual IEnumerable<TEntity> Get(
            Expression<Func<TEntity, bool>> filter = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
            Expression<Func<TEntity, object>>[] includes)
        {
            IQueryable<TEntity> query = dbSet;

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

             if (includes != null)
           {
              query = includes.Aggregate(query, 
                  (current, include) => current.Include(include));
            }

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

Consume it like this

var query = context.Customers
               .Get(x=>x.Id>1,null,
                   c => c.Address,
                   c => c.Orders.Select(o => o.OrderItems));

Similar SO question

Romano Zumbé
  • 7,893
  • 4
  • 33
  • 55
Eldho
  • 7,795
  • 5
  • 40
  • 77
  • Whoever uses this method must know and enumerate all included properties. And if someone decides to change property name, then he should Ctrl+Shift+F through a project and change all textual usages. And if someone adds a property which should be included eveyrwhere, then he should find all usages and add ",NewProperty" to every string. Sounds like SRP violation. I cannot believe that someone like [tdykstra](https://github.com/tdykstra) can write bad code, so there should be something I just can't understand and it makes me feel sad :( – Yeldar Kurmangaliyev May 31 '17 at 09:22
  • The code I have put is been in msdn. I have made a method with overload that is using lamda expression where you don't need to use string. Please see this https://stackoverflow.com/questions/5376421/ef-including-other-entities-generic-repository-pattern – Eldho May 31 '17 at 09:28
  • It throws argument null exception ;/ – Nerf May 31 '17 at 09:35
  • Can you tell me which line. I haven't tested it. – Eldho May 31 '17 at 10:24