当您拥有更大的数据库时,如何使用实体框架在c#中正确实现存储库模式?
我们应该为DAL(数据访问层)中实现Repository接口的每个表定义类,还是在业务层中定义这样的对象?
Repository<RetailerMarketplace> retailerMarketplaceRepo = null;
Repository<Marketplace> marketplaceRepo = null;
Repository<Product> productRepo = null;
Repository<OP_FLAGS> opFlagsRepo = null;
Repository<RetailerMarketplaceAttributeMapping> retailerMPAttributesMappingRepo = null;
Repository<EbayVariation> ebayVariationRepo = null;
Repository<ProductIsListed> productIsListedRepo = null;
Repository<Skus_OpFlags> skusOpFlagsRepo = null;
目前我已经定义了如上所述的对象,但我很困惑定义对象并在DAL或业务层中使用它们的正确方法是什么?
不要在业务层中创建任何Repository
对象。您应该将工作单元模式与存储库模式一起使用。DAL应该有一个工作单元类,它只将必需的存储库作为属性公开。这个工作类单元充当业务层和数据访问层之间的唯一网关。
例如,假设我有两个实体Foo
和Bar
,其结构如下:
public class Foo
{
public int FooId { get; set; }
public virtual ICollection<Bar> Bars { get; set; }
}
public class Bar
{
public int BarId { get; set; }
public int FooId { get; set; }
public virtual Foo Foo { get; set; }
}
我的UnitOfWork
类可能如下所示:
public class UnitOfWork
{
private Repository<Foo> foos;
public Repository<Foo> Foos
{
get
{
if(foos == null)
foos = new Repository<Foo>();
return foos;
}
}
...
}
就为每个实体定义存储库而言,您需要决定真正需要包含哪些实体。例如,我的UnitOfWork
不包括Repository<Bar>
。也许我这样做是因为我可以通过关联Foo
上的链接属性访问所有Bar
,而在我的域中单独查找Bar
是没有意义的。一句话:这完全取决于你的域,你公开了哪些存储库。只要明智地选择。
本文由ASP编写。NET/MVC团队,但其中的存储库/工作单元原则是使用实体框架的任何东西的良好实践。无论你是否使用MVC,这都是一本不错的读物。
EF有内置的存储库对象,它们的类型为DbSet,EF会自行初始化。所以在你的代码示例中,它们会像:
public DbSet<RetailerMarketplace> RetailerMarketplaces { get; set; }
public DbSet<Marketplace> MarketPlaces { get; set; }
那么,为什么要有一个额外的存储库层呢?
其中一个原因可能是能够伪造存储库对象,因为DbSet没有提供可用于模拟或伪造的接口。例如,让我们从IRepostory的接口类型创建一个通用存储库类。在这种情况下,类Repository将为任何模型T封装DbSet。
public interface IRepository<T> where T : class
{
void Add(T model);
void Edit(T model);
void Delete(T model);
T Get(object id);
IQueryable<T> List();
}
public class Repository<T> : IRepository<T> where T : class
{
DatabaseContext context;
DbSet<T> dbSet;
public Repository(DatabaseContext context)
{
this.context = context;
this.dbSet = context.Set<T>();
}
public void Add(T model)
{
dbSet.Add(model);
}
public void Edit(T model)
{
dbSet.Attach(model);
context.Entry(model).State = EntityState.Modified;
}
public void Delete(T model)
{
if (context.Entry(model).State == EntityState.Detached)
{
dbSet.Attach(model);
}
dbSet.Remove(model);
}
public T Get(object id)
{
return dbSet.Find(id);
}
public IQueryable<T> List()
{
return dbSet;
}
}
实例化存储库
var context = new DbContext();
var repo = new Repository<Marketplace>(context);
上面的上下文是UoW对象Repo是实例化的存储库对象。要创建一个伪对象,您需要从IRepository派生。