UnitOfWork或Repository中的DBContext SaveChanges方法?哪个更好?

时间:2016-04-18 10:35:32

标签: c# asp.net-mvc entity-framework repository-pattern

我正在尝试在MVC应用程序中首次使用Unit Of Work模式,该模式已经遵循具有Entity Framework DbContext的存储库模式。 我的问题是关于调用Savechanges()方法的最佳位置/实践。

我看到了两种方法:

  1. 在工作单元类中调用它(Asp.Net site中提到的方法)
  2. 在Repository类中调用
  3. 对于第一种方法,我们必须在Controller中注入的UnitOfWork实例上调用SaveChanges()。 对于第二种方法,SaveChanges()将封装在Repository中,所有Controller需要做的是在Repository中调用方法(由UnitOfWork提供),SaveChanges()将在Repository中调用。

    方法1:

     public class PostsController : Controller
     {
        private readonly IRepository<Post> _postRepository;
        private readonly IRepository<Category> _categoryRepository;
        private readonly IUnitOfWork _uow;
        public PostsController(IUnitOfWork uow)
        {
            if (uow == null)
                throw new ArgumentNullException(nameof(uow));
    
            _uow = uow;
            _postRepository = uow.Repository<Post>();
            _categoryRepository = uow.Repository<Category>();
        }
    
        [HttpPost]
        public ActionResult Create(Post post)
        {            
            if (ModelState.IsValid)
            {
                _postRepository.Add(post);
                _uow.SaveChanges();
            }
            return View(post);
        }
    }
    
    public class UnitOfWork : IUnitOfWork
    {
        private CodingSoldierDbContext _dbContext;
        private Dictionary<Type, object> _repositories = new Dictionary<Type, object>();
        public UnitOfWork(DbContext dbContext)
        {
            if (dbContext == null)
                throw new ArgumentNullException(nameof(dbContext));
            _dbContext = dbContext as CodingSoldierDbContext;
        }
        public IRepository<T> Repository<T>() where T : class
        {
            if (_repositories.Keys.Contains(typeof(T)))
            {
                return _repositories[typeof(T)] as IRepository<T>;
            }
            IRepository<T> repository = new Repository<T>(_dbContext);
            _repositories.Add(typeof(T), repository);
            return repository;
        }
        public void SaveChanges()
        {
            _dbContext.SaveChanges();
        }
    }
    
    public class Repository<T> : IRepository<T> where T : class
    {
        CodingSoldierDbContext _dbContext;
        public Repository(DbContext dbContext)
        {
            if (dbContext == null)
                throw new ArgumentNullException(nameof(dbContext));
            _dbContext = dbContext as CodingSoldierDbContext;
        }
    
        public void Add(T item)
        {
            _dbContext.Set<T>().Add(item);
            //_dbContext.SaveChanges();
        }
    }
    

    方法2: 不添加代码,以便问题仍然很短。 在方法1中,在Controller中的Create方法中,删除以下行:

    _uow.SaveChanges();
    

    从UnitOfWork中删除“SaveChanges”方法定义。

    取消注释存储库类中的注释行:

    _dbContext.SaveChanges()
    

    我觉得第二种方法比第一种方法更好,因为控制器中的意义代码更清晰,而且SaveChanges是直接与DbContext交互的同一类(Repository)的责任。

    任何人,如果您有任何理由我们应该遵循第一种方法,请告诉我吗?

2 个答案:

答案 0 :(得分:4)

我更喜欢在UnitOfWork上下文中实现SaveChanges,因为如果您从多个存储库编辑多个实体,则不希望在每个存储库上执行保存更改。

示例:

var unitOfWork = UnitOfWorkFactory.Create();
var categoryRepo = unitOfWork.GetRepository<Category>();
var postRepo= unitOfWork.GetRepository<Post>();

var cat = new Category("name");
categoryRepo.Add(cat);

var post = new Post("Title", "Message");
post.Category = cat;
postRepo.Add(post );

unitOfWork.SaveChanges();

保存完整的上下文(在一个过渡中)更容易。

答案 1 :(得分:0)

两者。在UOW中,您需要保存对复合存储库使用的上下文的更改。您还需要在存储库中保存更改方法,如

public void SaveChanges() 
{
    context.SaveChanges(); 
}

对于独立使用的存储库