Reputation: 39374
I am trying to create a multiple include method in my repository to use as follows:
repository.Include<Post>(x => x.Images, x => x.Tags).First(x => x.Id == 1)
I tried something as:
public IQueryable<T> Include<T>(params Expression<Func<T, Object>>[] paths) where T : class {
return paths.Aggregate(_context.Set<T>(), (x, path) => x.Include(path));
} // Include
But I get the error:
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Entity.DbSet'.
Note that the original include is the following:
public static IQueryable Include( this IQueryable source, Expression> path ) where T : class;
Can I make this work without turning my repository method into static?
Thank You,
Miguel
Upvotes: 6
Views: 9672
Reputation: 1048
I guess the shortest way is as follows:
public static class LinqExtensions
{
/// <summary>
/// Acts similar of .Include() LINQ method, but allows to include several object properties at once.
/// </summary>
public static IQueryable<T> IncludeMultiple<T>(this IQueryable<T> query, params Expression<Func<T, object>>[] paths)
where T : class
{
foreach (var path in paths)
query = query.Include(path);
return query;
}
}
Upvotes: 0
Reputation: 149
public ICollection<SomeClass> Filter(string name, int skip, int take,out int total, params Expression<Func<SomeClass, object>>[] includeProperties) {
IQueryable<SomeClass> query = Session.All<SomeClass>().AsNoTracking();
//query = includeProperties.Aggregate(query, (current, property) => current.Include(property));
foreach (var property in includeProperties){
query = query.Include(property);
}
if (!string.IsNullOrWhiteSpace(name)){
query = query.Where(x => x.Name.Contains(name));
var page = query.OrderBy(x => x.Name)
.Skip(skip)
.Take(take)
.GroupBy(p => new{Total = query.Count()})
.FirstOrDefault();
total = (page != null) ? page.Key.Total : 0;
if (page == null) {
return new List<SomeClass>();
}
return page.ToList();
} else {
var page = query.OrderBy(x => x.Name)
.Skip(skip)
.Take(take)
.GroupBy(p => new { Total = query.Count() })
.FirstOrDefault();
total = (page != null) ? page.Key.Total : 0;
if (page == null) {
return new List<SomeClass>();
}
return page.ToList();
}
}
Upvotes: 0
Reputation:
If you really want to create your own .Include
non-extension method that allows for multiple paths in one call, internally translating to the already provided .Include
method, you can do something like
public IQueryable<T> Include<T>(params Expression<Func<T, object>>[] paths)
where T : class
{
IQueryable<T> query = _context.Set<T>();
foreach (var path in paths)
query = query.Include(path);
return query;
}
This is pretty close to what you have already, but avoids the pitfall with Enumerable.Aggregate
that you encountered: you'd have the same problem if you replace IQueryable<T> query
with var query
in my version.
Note that using many .Include
may harm performance. If it does in your situation, you can rewrite it to use multiple queries, which you can run one after the other in a transaction.
Personally, as you can call the already provided .Include
extension method (using System.Data.Entity;
) on any IQueryable
, I'd just write it as:
repository.Posts.Include(x => x.Images).Include(x => x.Tags).First(x => x.Id == 1)
Upvotes: 9