C# 使用存储库模式,我们应该为DAL中的每个表或业务层中的对象定义类吗?
当您有一个较大的数据库时,如何在c#with entity framework中正确实现存储库模式 我们应该在DAL(数据访问层)中为实现存储库接口的每个表定义类,还是在业务层中定义这样的对象C# 使用存储库模式,我们应该为DAL中的每个表或业务层中的对象定义类吗?,c#,entity-framework,repository-pattern,C#,Entity Framework,Repository Pattern,当您有一个较大的数据库时,如何在c#with entity framework中正确实现存储库模式 我们应该在DAL(数据访问层)中为实现存储库接口的每个表定义类,还是在业务层中定义这样的对象 Repository<RetailerMarketplace> retailerMarketplaceRepo = null; Repository<Marketplace> marketplaceRepo = null; Repository<Product> pro
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;
Repository retailerMarketplaceRepo=null;
存储库marketplaceRepo=null;
存储库productRepo=null;
存储库opFlagsRepo=null;
Repository retailerMPAttributesMappingRepo=null;
存储库ebayVariationRepo=null;
存储库productIsListedRepo=null;
存储库skusOpFlagsRepo=null;
目前我已经定义了如上所述的对象,但我不清楚在DAL或业务层中定义和使用对象的正确方法是什么?不要在业务层中创建任何
存储库对象。您应该将工作单元模式与存储库模式一起使用。DAL应该有一个工作类单元,只将必要的存储库作为属性公开。这个工作类单元充当业务层和数据访问层之间的唯一网关
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;
例如,假设我有两个实体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; }
}
public class UnitOfWork
{
private Repository<Foo> foos;
public Repository<Foo> Foos
{
get
{
if(foos == null)
foos = new Repository<Foo>();
return foos;
}
}
...
}
就为每个实体定义存储库而言,您需要决定真正需要包括哪些实体。例如,我的UnitOfWork
不包括存储库
。也许我这样做是因为我可以通过它们关联的Foo
上的链接属性访问所有Bar
,而在我的域中单独查找Bar
是没有意义的。一句话:这完全取决于您的域,您公开了哪些存储库。只要明智地选择
由ASP.NET/MVC团队编写,但其中的存储库/工作单元原则是使用实体框架的良好实践。无论您是否使用MVC,这都是一本很好的读物。不要在您的业务层中创建任何存储库
对象。您应该将工作单元模式与存储库模式一起使用。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; }
}
public class UnitOfWork
{
private Repository<Foo> foos;
public Repository<Foo> Foos
{
get
{
if(foos == null)
foos = new Repository<Foo>();
return foos;
}
}
...
}
就为每个实体定义存储库而言,您需要决定真正需要包括哪些实体。例如,我的UnitOfWork
不包括存储库
。也许我这样做是因为我可以通过它们关联的Foo
上的链接属性访问所有Bar
,而在我的域中单独查找Bar
是没有意义的。一句话:这完全取决于您的域,您公开了哪些存储库。只要明智地选择
由ASP.NET/MVC团队编写,但其中的存储库/工作单元原则是使用实体框架的良好实践。无论您是否使用MVC,这都是一个很好的读物。EF有内置的存储库对象,它们属于DbSet类型,EF会自行初始化。因此,在您的代码示例中,它们如下所示:
public DbSet<RetailerMarketplace> RetailerMarketplaces { get; set; }
public DbSet<Marketplace> MarketPlaces { get; set; }
公共数据库集RetailerMarketplaces{get;set;}
公共数据库集市场{get;set;}
那么,为什么要有一个额外的存储库层呢
一个原因可能是能够伪造存储库对象,因为DbSet不提供可用于模拟或伪造的接口。例如,让我们从接口类型IRepostory创建一个通用存储库类。在本例中,类存储库将封装任何模型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;
}
}
公共接口i假设,其中T:class
{
void-Add(T型);
无效编辑(T型);
无效删除(T型);
T Get(对象id);
IQueryable列表();
}
公共类存储库:IRepository,其中T:class
{
数据库上下文;
DbSet-DbSet;
公共存储库(数据库上下文)
{
this.context=上下文;
this.dbSet=context.Set();
}
公共空间添加(T型)
{
添加(模型);
}
公共无效编辑(T模型)
{
附加(模型);
context.Entry(model.State=EntityState.Modified;
}
公共作废删除(T型)
{
if(context.Entry(model.State==EntityState.Detached)
{
附加(模型);
}
删除(模型);
}
公共T获取(对象id)
{
返回dbSet.Find(id);
}
公共可查询列表()
{
返回dbSet;
}
}
实例化存储库
var context = new DbContext();
var repo = new Repository<Marketplace>(context);
var context=new DbContext();
var repo=新存储库(上下文);
上面的上下文是UoW对象。Repo是实例化的存储库对象。要创建假对象,您需要从IRepository派生。EF有内置的存储库对象,它们属于DbSet类型,EF会自行初始化。因此,在您的代码示例中,它们如下所示:
public DbSet<RetailerMarketplace> RetailerMarketplaces { get; set; }
public DbSet<Marketplace> MarketPlaces { get; set; }
公共数据库集RetailerMarketplaces{get;set;}
公共数据库集市场{get;set;}
那么,为什么要有一个额外的存储库层呢
一个原因可能是能够伪造存储库对象,因为DbSet不提供可用于模拟或伪造的接口。例如,让我们从接口类型IRepostory创建一个通用存储库类。在本例中,类存储库将封装任何模型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;
}
}
公共接口i假设,其中T:class
{
void-Add(T型);
无效编辑(T型);
无效删除(T型);
T Get(对象id);
IQueryable列表();
}
公共类存储库:IRepository,其中T:class
{
数据库上下文;
DbSet-DbSet;
公共存储库