C# 多层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();

我创建了一个应用程序,它使用多个Visual Studio项目作为ASP.NET MVC应用程序的层。我有一个数据访问层、业务逻辑层和表示层

解决方案如下所示:

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(模型);
}
公共作废删除(图书模型)
{