我也有同样的经历。当我实现存储库模式时,我希望能够使用 DbSet<T> 实现的 IQueryable<T> 和 IEnumerable<T>,而不暴露 DbSet<T>(旧信息隐藏)
因此我认为让所有的 IQueryable / IEnumerable 函数调用 Repository 中 DbSet<T> 的相应函数就足够了。
直到今天,这对于我所有的 IQueryable<T> 函数来说已经足够了。今天我发现除了 IQueryable.Include 有你描述的同样的问题。没有编译器错误,但没有加载数据。
经过广泛的结果,我发现原因在QueryableExtensions.Include Method (IQueryable, String)的 MSDN 描述中有所描述
此扩展方法调用源 IQueryable 对象的 Include(String) 方法(如果存在此类方法)。如果源 IQueryable 没有匹配方法,则此方法不执行任何操作。
所以我所要做的就是在我的存储库中编写一个匹配的包含语句,该语句将调用相应的 DbSet 存储库。IQueryable / IEnumerable 函数只是调用 DbSet 的相应函数:
public class Repository<T> :
System.Linq.IQueryable<T>, System.Collections.Generic.IEnumerable<T>,
System.Linq.IQueryable, System.Collections.IEnumerable
where T : class, new()
{
public Repository(DbContext dbContext)
{
this.dbContext = dbContext;
this.dbSet = dbContext.Set<T>();
}
public readonly DbSet<T> dbSet;
private readonly DbContext dbContext;
public virtual DbQuery<T> Include(string path)
{
return this.dbSet.Include(path);
}
// other Repository functions: Find / Add / Update / Remove etc
为了完整性,IQueryable / IEnumerable 实现:
#region IQueryable
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return ((IQueryable<T>)this.dbSet).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this.dbSet).GetEnumerator();
}
Type IQueryable.ElementType
{
get { return ((IQueryable<T>)this.dbSet).ElementType; }
}
System.Linq.Expressions.Expression IQueryable.Expression
{
get { return ((IQueryable)this.dbSet).Expression; }
}
IQueryProvider IQueryable.Provider
{
get { return ((IQueryable)this.dbSet).Provider; }
}
#endregion IQueryable
现在以下工作,地址包括:
using (MyDbContext dbContext = new MyDbContext(...))
{
Repository<Customer> customers = new Repository<Customer>(dbContext);
var happyCustomers = customers
.Include(customer => customer.Address)
.Where(customer => customer.IsHappy);
Show(happyCustomers);
}