0

I use repository pattern and Entity Framework in C# with this generic methods:

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();
        }
    }

    public virtual TEntity GetByID(object id)
    {
        return dbSet.Find(id);
    }

Now I want write an overload for GetByID to accept includeproperties just like Get method that I have used. Something like this:

    public virtual TEntity GetByID(object id, string includeProperties = "")
    {
        IQueryable<TEntity> query = dbSet;
        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }            
        return ???
    }

What should I return? Any suggestion?

Azarsa
  • 1,278
  • 3
  • 27
  • 37

1 Answers1

2

This is fairly dependent on your objects-- Do your entities implement a common interface that declares an ID property? In that scenario, you could query.SingleOrDefault(e => e.Id == id), however, in what seems the more likely scenario, you would need to either pass in a predicate to match or re-implement the Find() functionality.

In DBContext Find with Includes - where lambda with Primary keys, RBrowning99 pulled the entitiy keys from the context and matched based the first key:

public DALEntity Get(string ID, IEnumerable<string> IncludeEntities = null)
{
    var set = ((IObjectContextAdapter)context).ObjectContext.CreateObjectSet<DALEntity>();
    var entitySet = set.EntitySet;
    string[] keyNames = entitySet.ElementType.KeyMembers.Select(k => k.Name).ToArray();

    IQueryable<DALEntity> query = dbSet;
    query = IncludeEntities.Aggregate(query, (current, includePath) => current.Include(includePath));

    query = query.Where(keyNames[0] + "= @0", ID);
    return query.FirstOrDefault();
}
Community
  • 1
  • 1
DanS
  • 792
  • 5
  • 10
  • 1
    hmm... he doesn't need a dynamic where clause that searches through the context (which is completely unspecified here), finds and uses the pk, he's already defining his where clause with 'filter' as a parameter. all he needs is the query.FirstOrDefault().. – Brett Caswell Sep 24 '14 at 16:47
  • actually.. disregard my last comment there.. he's not passing a way to filter (it would seem there is going to have to be some sort of imperative/reflection here in the absence of declaration), so looking up the primary key is probably the option worth considering/taking.. – Brett Caswell Sep 24 '14 at 17:00
  • No overload for method 'Where' takes 2 arguments – Azarsa Sep 24 '14 at 17:54
  • While I didn't write the referenced code, its likely based off of Dynamic LINQ extensions --> http://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library – DanS Sep 24 '14 at 18:29