如果拥有更大的数据库,如何在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或业务层中定义对象和使用它们的正确方法感到困惑?
答案 0 :(得分:2)
不要在业务层中创建任何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>
。也许我这样做是因为我可以通过关联的Bar
上的链接属性访问所有Foo
,但在我的域中查找Bar
是没有意义的它自己的。底线:这完全取决于您的域名您公开的存储库。只要明智地选择。
This article由ASP.NET / MVC团队编写,但其中的存储库/工作原理单元是使用Entity Framework的任何实践的良好实践。无论您是否使用MVC,都可以很好地阅读。
答案 1 :(得分:2)
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派生。