C# 多层ASP.NET MVC应用程序中的实体框架上下文
我创建了一个应用程序,它使用多个Visual Studio项目作为ASP.NET MVC应用程序的层。我有一个数据访问层、业务逻辑层和表示层 解决方案如下所示:C# 多层ASP.NET MVC应用程序中的实体框架上下文,c#,asp.net-mvc,entity-framework,dbcontext,C#,Asp.net Mvc,Entity Framework,Dbcontext,我创建了一个应用程序,它使用多个Visual Studio项目作为ASP.NET MVC应用程序的层。我有一个数据访问层、业务逻辑层和表示层 解决方案如下所示: public class RepositoryDal: IRepositoryDal { private readonly DatabaseContext context; public RepositoryDal() { context = new DatabaseContext();
public class RepositoryDal: IRepositoryDal
{
private readonly DatabaseContext context;
public RepositoryDal()
{
context = new DatabaseContext();
}
public T Add<T>(T entity) where T : Entity
{
return context.Set<T>().Add(entity);
}
public void Delete<T>(T entity) where T : Entity
{
context.Set<T>().Remove(entity);
}
public IQueryable<T> GetAll<T>() where T : Entity
{
return context.Set<T>();
}
public T GetById<T>(int id) where T : Entity
{
return context.Set<T>().FirstOrDefault(x => x.Id == id);
}
public bool HasChanges()
{
return context.ChangeTracker.HasChanges();
}
public void Save()
{
context.SaveChanges();
}
}
public class UnitOfWork : DbContext, IUnitOfWork
{
public DbSet<Book> DBBooks { get; set; }
public DbSet<Shelf> DBShelves { get; set; }
private IBookRepository _bookRepository;
public IBookRepository BookRepository
{
get
{
if (_bookRepository == null)
_bookRepository = new BookRepository(this);
return _bookRepository;
}
}
private IShelfRepository _shelfRepository;
public IShelfRepository ShelfRepository
{
get
{
if (_shelfRepository == null)
_shelfRepository = new ShelfRepository(this);
return _shelfRepository;
}
}
public UnitOfWork() : base("Name=MyDB") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// If you use fluent syntax mapping, initialize those here
modelBuilder.Configurations.Add(new BookMap());
modelBuilder.Configurations.Add(new ShelfMap());
}
public void Commit()
{
SaveChanges();
}
}
我使用的存储库如下所示:
public class RepositoryDal: IRepositoryDal
{
private readonly DatabaseContext context;
public RepositoryDal()
{
context = new DatabaseContext();
}
public T Add<T>(T entity) where T : Entity
{
return context.Set<T>().Add(entity);
}
public void Delete<T>(T entity) where T : Entity
{
context.Set<T>().Remove(entity);
}
public IQueryable<T> GetAll<T>() where T : Entity
{
return context.Set<T>();
}
public T GetById<T>(int id) where T : Entity
{
return context.Set<T>().FirstOrDefault(x => x.Id == id);
}
public bool HasChanges()
{
return context.ChangeTracker.HasChanges();
}
public void Save()
{
context.SaveChanges();
}
}
public class UnitOfWork : DbContext, IUnitOfWork
{
public DbSet<Book> DBBooks { get; set; }
public DbSet<Shelf> DBShelves { get; set; }
private IBookRepository _bookRepository;
public IBookRepository BookRepository
{
get
{
if (_bookRepository == null)
_bookRepository = new BookRepository(this);
return _bookRepository;
}
}
private IShelfRepository _shelfRepository;
public IShelfRepository ShelfRepository
{
get
{
if (_shelfRepository == null)
_shelfRepository = new ShelfRepository(this);
return _shelfRepository;
}
}
public UnitOfWork() : base("Name=MyDB") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// If you use fluent syntax mapping, initialize those here
modelBuilder.Configurations.Add(new BookMap());
modelBuilder.Configurations.Add(new ShelfMap());
}
public void Commit()
{
SaveChanges();
}
}
这很有效。但如果我这样做,它将无法正常工作:
public class ShelfBll: IShelfBll
{
private readonly IRepositoryDal _repositoryDal;
public ShelfBll()
{
_repositoryDal = new RepositoryDal();
}
public Shelf AddShelf(Shelf shelf)
{
shelf = _repositoryDal.Add(shelf);
_repositoryDal.Save();
return shelf;
}
...
}
问题是,我将书连接到书架,书架通过另一个业务逻辑层类检索。通过这样做,我失去了实体框架上下文。
发生的情况是,应用程序将不会连接到工具架,但它将创建一个新的工具架。这意味着在此之后,我将有两个同名的书架
如何解决此问题?与其隐藏每个存储库后面的单独DB上下文对象,不如公开一个中心对象,该对象本身类似于DB上下文,并且跨越所有存储库。类似于“工作单元”的对象 我有,但模式仍然有效 本质上,目标是允许消费代码执行如下简单操作:
using (var uow = new UnitOfWork())
{
// all database interactions happen inside of here
var book = new Book();
// set a bunch of properties, etc.
uow.BookRepository.Add(book);
uow.ShelfRepository.Add(someShelf);
// and so on...
uow.Commit();
}
其思想是,存储库本身并不是数据库交互的主要焦点。它们是工作单元的属性,而工作单元本身就是重点。它可能看起来像这样:
public class RepositoryDal: IRepositoryDal
{
private readonly DatabaseContext context;
public RepositoryDal()
{
context = new DatabaseContext();
}
public T Add<T>(T entity) where T : Entity
{
return context.Set<T>().Add(entity);
}
public void Delete<T>(T entity) where T : Entity
{
context.Set<T>().Remove(entity);
}
public IQueryable<T> GetAll<T>() where T : Entity
{
return context.Set<T>();
}
public T GetById<T>(int id) where T : Entity
{
return context.Set<T>().FirstOrDefault(x => x.Id == id);
}
public bool HasChanges()
{
return context.ChangeTracker.HasChanges();
}
public void Save()
{
context.SaveChanges();
}
}
public class UnitOfWork : DbContext, IUnitOfWork
{
public DbSet<Book> DBBooks { get; set; }
public DbSet<Shelf> DBShelves { get; set; }
private IBookRepository _bookRepository;
public IBookRepository BookRepository
{
get
{
if (_bookRepository == null)
_bookRepository = new BookRepository(this);
return _bookRepository;
}
}
private IShelfRepository _shelfRepository;
public IShelfRepository ShelfRepository
{
get
{
if (_shelfRepository == null)
_shelfRepository = new ShelfRepository(this);
return _shelfRepository;
}
}
public UnitOfWork() : base("Name=MyDB") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// If you use fluent syntax mapping, initialize those here
modelBuilder.Configurations.Add(new BookMap());
modelBuilder.Configurations.Add(new ShelfMap());
}
public void Commit()
{
SaveChanges();
}
}
公共类UnitOfWork:DbContext,IUnitOfWork
{
公共DbSet DBBooks{get;set;}
公共DbSet DBShelves{get;set;}
私人IBookRepository\u图书存储库;
公共IBookRepository图书存储库
{
得到
{
如果(_bookRepository==null)
_bookRepository=新的bookRepository(此);
返回(bookRepository);;
}
}
私人IShelfRepository_Shelfrespository;
公共存储库搁置
{
得到
{
如果(_shelfRepository==null)
_shelfrespository=新的shelfrespository(本);
返回_shelfrespository;
}
}
public UnitOfWork():base(“Name=MyDB”){}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
//如果您使用fluent语法映射,请在此处初始化它们
modelBuilder.Configurations.Add(newbookmap());
添加(新的ShelfMap());
}
公共无效提交()
{
保存更改();
}
}
任何给定的存储库,与您拥有的存储库非常相似,大多只是对DB上下文的传递:
public class BookRepository : IBookRepository
{
private UnitOfWork _unitOfWork;
public IQueryable<Book> Books
{
get { return _unitOfWork.DBBooks; }
}
public BookRepository(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void Add(Book model)
{
_unitOfWork.DBBooks.Add(model);
}
public void Remove(Book model)
{
_unitOfWork.DBBooks.Remove(model);
}
}
公共类图书存储库:IBookRepository
{
私人工作单位(Unitof Work);;
公共图书馆图书
{
获取{return\u unitOfWork.DBBooks;}
}
公共图书存储库(UnitOfWork UnitOfWork)
{
_unitOfWork=unitOfWork;
}
公共空白添加(书本模型)
{
_unitOfWork.DBBooks.Add(模型);
}
公共作废删除(图书模型)
{
_unitOfWork.DBBooks.Remove(模型);
}
}
(请注意,我的原始代码严格使用依赖项注入,这样使用代码的人就不会真正看到这些实现,而只看到接口。因此公共DBSet
属性仍然只是DAL的内部属性。您可能需要根据需要进行调整。)
此设计中工作单元背后的思想是,您有一个单独的对象来协调实际的数据库交互,而存储库挂起该对象。这允许您与实体框架数据库上下文公开的数据进行完全交互,并在最后进行一次保存(或回滚)。当然,另外一个好处是,当逻辑从一个存储库切换到另一个存储库时,您不会提交完成了一半的更改,整个过程被包装在一种隐式事务中。而不是隐藏每个存储库后面的单独DB上下文对象,公开一个中心对象,该对象本身类似于数据库上下文,并且跨越所有存储库。类似于“工作单元”的对象 我有,但模式仍然有效 本质上,目标是允许消费代码执行如下简单操作:
using (var uow = new UnitOfWork())
{
// all database interactions happen inside of here
var book = new Book();
// set a bunch of properties, etc.
uow.BookRepository.Add(book);
uow.ShelfRepository.Add(someShelf);
// and so on...
uow.Commit();
}
其思想是,存储库本身并不是数据库交互的主要焦点。它们是工作单元的属性,而工作单元本身就是重点。它可能看起来像这样:
public class RepositoryDal: IRepositoryDal
{
private readonly DatabaseContext context;
public RepositoryDal()
{
context = new DatabaseContext();
}
public T Add<T>(T entity) where T : Entity
{
return context.Set<T>().Add(entity);
}
public void Delete<T>(T entity) where T : Entity
{
context.Set<T>().Remove(entity);
}
public IQueryable<T> GetAll<T>() where T : Entity
{
return context.Set<T>();
}
public T GetById<T>(int id) where T : Entity
{
return context.Set<T>().FirstOrDefault(x => x.Id == id);
}
public bool HasChanges()
{
return context.ChangeTracker.HasChanges();
}
public void Save()
{
context.SaveChanges();
}
}
public class UnitOfWork : DbContext, IUnitOfWork
{
public DbSet<Book> DBBooks { get; set; }
public DbSet<Shelf> DBShelves { get; set; }
private IBookRepository _bookRepository;
public IBookRepository BookRepository
{
get
{
if (_bookRepository == null)
_bookRepository = new BookRepository(this);
return _bookRepository;
}
}
private IShelfRepository _shelfRepository;
public IShelfRepository ShelfRepository
{
get
{
if (_shelfRepository == null)
_shelfRepository = new ShelfRepository(this);
return _shelfRepository;
}
}
public UnitOfWork() : base("Name=MyDB") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// If you use fluent syntax mapping, initialize those here
modelBuilder.Configurations.Add(new BookMap());
modelBuilder.Configurations.Add(new ShelfMap());
}
public void Commit()
{
SaveChanges();
}
}
公共类UnitOfWork:DbContext,IUnitOfWork
{
公共DbSet DBBooks{get;set;}
公共DbSet DBShelves{get;set;}
私人IBookRepository\u图书存储库;
公共IBookRepository图书存储库
{
得到
{
如果(_bookRepository==null)
_bookRepository=新的bookRepository(此);
返回(bookRepository);;
}
}
私人IShelfRepository_Shelfrespository;
公共存储库搁置
{
得到
{
如果(_shelfRepository==null)
_shelfrespository=新的shelfrespository(本);
返回_shelfrespository;
}
}
public UnitOfWork():base(“Name=MyDB”){}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
//如果您使用fluent语法映射,请在此处初始化它们
modelBuilder.Configurations.Add(newbookmap());
添加(新的ShelfMap());
}
公共无效提交()
{
保存更改();
}
}
任何给定的存储库,与您拥有的存储库非常相似,大多只是对DB上下文的传递:
public class BookRepository : IBookRepository
{
private UnitOfWork _unitOfWork;
public IQueryable<Book> Books
{
get { return _unitOfWork.DBBooks; }
}
public BookRepository(UnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void Add(Book model)
{
_unitOfWork.DBBooks.Add(model);
}
public void Remove(Book model)
{
_unitOfWork.DBBooks.Remove(model);
}
}
公共类图书存储库:IBookRepository
{
私人工作单位(Unitof Work);;
公共图书馆图书
{
获取{return\u unitOfWork.DBBooks;}
}
公共图书存储库(UnitOfWork UnitOfWork)
{
_unitOfWork=unitOfWork;
}
公共空白添加(书本模型)
{
_unitOfWork.DBBooks.Add(模型);
}
公共作废删除(图书模型)
{