我在Entity Framework Code First上使用Generic Repository模式。一切都工作正常,直到我需要在查询中包含更多实体。我成功地包含了一个实体,但现在我无法弄清楚如何包含多个实体。看看到目前为止我得到了什么:
public IQueryable<TEntity> GetQuery<TEntity>() where TEntity : class
{
var entityName = GetEntityName<TEntity>();
return _objectContext.CreateQuery<TEntity>(entityName);
}
public IList<TEntity> GetQueryWithInclude<TEntity>(string toInclude) where TEntity : class
{
var entityName = GetEntityName<TEntity>();
return _objectContext.CreateQuery<TEntity>(entityName).Include(toInclude).ToList();
}
private string GetEntityName<TEntity>() where TEntity : class
{
return string.Format("{0}.{1}", _objectContext.DefaultContainerName, _pluralizer.Pluralize(typeof(TEntity).Name));
}
我尝试做但不起作用的是将一个字符串数组传递给一个函数,然后尝试在查询之上“追加”包含。我想知道如果我调用GetQueryWithInclude并一次传递一个实体名称(实际上是一个导航属性)来聚合查询结果,但我担心这可能会在每次调用时复制查询结果...您认为最好的方法是什么?
提前致谢!
更新
以下是我想要实现的一个例子:
public IQueryable GetQueryWithIncludes(string[] otherEntities)
{
var entityName = GetEntityName<TEntity>();
//now loop over the otherEntities array
//and append Include extensions to the query
//so inside the loop, something like:
_objectContext.GetQuery<TEntity>(entityName).Include(otherEntities[index]);
}
答案 0 :(得分:129)
仅使用IQueryable上的Include扩展名。它在EF 4.1组件中可用。如果您不想在上层中引用该程序集,请在数据访问程序集中创建包装器扩展方法。
这里有例子:
public static IQueryable<T> IncludeMultiple<T>(this IQueryable<T> query, params Expression<Func<T, object>>[] includes)
where T : class
{
if (includes != null)
{
query = includes.Aggregate(query,
(current, include) => current.Include(include));
}
return query;
}
您将使用它,例如:
var query = context.Customers
.IncludeMultiple(
c => c.Address,
c => c.Orders.Select(o => o.OrderItems));
此查询将使用地址和订单加载所有客户,每个订单都将包含其订单商品。
答案 1 :(得分:3)
Say goodbye to the hardcoded ObjectQuery(T).Include calls
如果您正在使用EF&gt; 4,然后它内置,检查DbExtensions.Include on MSDN。
答案 2 :(得分:3)
//我在这里列出了最低限度。以下是如何使用它。
IQueryable<File> xg= UnitOfWork.Files.GetAllLazyLoad(d => d.FileId == 1,
r => r.FileCategory);
//where r.FileCategory is a navigational property.
//Interface
namespace Msh.Intranet.Repository.GenericRepoPattern
{
public interface IRepository<T> where T:class
{
IQueryable<T> GetAllLazyLoad(Expression<Func<T, bool>> filter, params Expression<Func<T, object>>[] children);
}
}
namespace Msh.Intranet.Repository.GenericRepoPattern
{
/// <summary>
/// The EF-dependent, generic repository for data access
/// </summary>
/// <typeparam name="T">Type of entity for this Repository.</typeparam>
public class EFRepository<T> : IRepository<T> where T : class
{
public EFRepository(DbContext dbContext)
{
if (dbContext == null)
throw new ArgumentNullException("dbContext");
DbContext = dbContext;
DbSet = DbContext.Set<T>();
}
protected DbContext DbContext { get; set; }
protected DbSet<T> DbSet { get; set; }
public virtual IQueryable<T> GetAllLazyLoad(Expression<Func<T, bool>> filter, params Expression<Func<T, object>>[] children)
{
children.ToList().ForEach(x=>DbSet.Include(x).Load());
return DbSet;
}
}
}
答案 3 :(得分:0)
对于实体框架,创建一个字符串列表来保存包含。参见下面的示例代码
public virtual IQueryable<TObject> Filter(Expression<Func<TObject, bool>> filter,
int skip = 0,
int take = int.MaxValue,
Func<IQueryable<TObject>, IOrderedQueryable<TObject>> orderBy = null,
IList<string> incudes = null)
{
var _resetSet = filter != null ? DbSet.AsNoTracking().Where(filter).AsQueryable() : DbSet.AsNoTracking().AsQueryable();
if (incudes != null)
{
foreach (var incude in incudes)
{
_resetSet = _resetSet.Include(incude);
}
}
if (orderBy != null)
{
_resetSet = orderBy(_resetSet).AsQueryable();
}
_resetSet = skip == 0 ? _resetSet.Take(take) : _resetSet.Skip(skip).Take(take);
return _resetSet.AsQueryable();
}
有关更多详细信息,请参见以下链接 http://bulletproofcoder.com/blog/using-include-in-a-generic-entity-framework-repository
在实体框架核心中,我们将使用 IIncludableQueryable 。参见下面的示例代码
public virtual IQueryable<TObject> Filter(Expression<Func<TObject, bool>> filter,
int skip = 0,
int take = int.MaxValue,
Func<IQueryable<TObject>, IOrderedQueryable<TObject>> orderBy = null,
Func<IQueryable<TObject>, IIncludableQueryable<TObject, object>> include = null)
{
var _resetSet = filter != null ? DbSet.AsNoTracking().Where(filter).AsQueryable() : DbSet.AsNoTracking().AsQueryable();
if (include != null)
{
_resetSet = include(_resetSet);
}
if (orderBy != null)
{
_resetSet = orderBy(_resetSet).AsQueryable();
}
_resetSet = skip == 0 ? _resetSet.Take(take) : _resetSet.Skip(skip).Take(take);
return _resetSet.AsQueryable();
}