我正在使用EF的存储库模式,我认为我已经在它上面销售,但仍有一个问题;
如果我想加载一个实体,那么最好的方法是什么?
例如,我有一个映射到实体的存储库:
public class EFFooRepository : IFooRepository
{
public IQueryable<Foo> GetFoo()
{
.....
}
}
如果我想获取Foo和Bar对象
,该怎么办?db.Foo.Include("Bar")
但我的存储库只返回Foo,那么我是否需要创建另一个方法GetFooAndBar?
有更好的方法吗?
答案 0 :(得分:1)
因此我认为让所有IQueryable / IEnumerable函数调用DbSet的相应函数就足够了。 T>在存储库中。
直到今天,这对我所有的IQueryable来说已经足够了T>功能。今天我发现除了IQueryable.Include有你描述的相同问题。没有编译器错误,但未加载数据。
经过广泛的结果后,我发现原因在QueryableExtensions.Include Method (IQueryable, String)
的MSDN描述中有所描述如果存在这样的方法,则此扩展方法将调用源IQueryable对象的Include(String)方法。 如果源IQueryable没有匹配方法,则此方法不执行任何操作。
所以我所要做的就是在我的存储库中编写一个匹配的include语句,它将调用相应的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);
}
答案 1 :(得分:0)
如果您启用了延迟加载,则可以稍后加载Bar
(当您要访问该属性时)。但是如果你想编写一个同时加载数据Foo
和Bar
的方法,则需要编写特定的存储库方法。