在之前的泛型仓储模式实现中,每个增删改都调用了savechanges方法,导致每次更新都提交了事务。

在实际开发过程中,我们经常遇到同时操作多张表数据,那么按照之前的写法,对数据库提交了多次操作,开启了多事务,不能保证数据的一致性,结合工作单元(unitofwork)是为了把多次操作放到同一事务中,要么都成功(commit),要么都失败(rollback),保证了数据的一致性。

 修改仓储类

先把仓储接口中增删改接口无返回(void)值类型,然后去仓储实现类去掉savechanges方法,交给uow统一处理

实现uow

把savechanges抽离出来,定义iunitofwork接口

namespace netcorewebapi.repository
{
    /// <summary>
    /// 接口
    /// </summary>
    public interface iunitofwork
    {
        /// <summary>
        /// 保存
        /// </summary>
        /// <returns></returns>
        int savechanges();
    }
}

实现iunitofwork接口

using system;
using microsoft.entityframeworkcore;

namespace netcorewebapi.repository
{
    /// <summary>
    /// 实现类
    /// </summary>
    public class unitofwork<tdbcontext> : iunitofwork where tdbcontext : dbcontext
    {
        /// <summary>
        /// dbcontext上下文
        /// </summary>
        private readonly tdbcontext _dbcontext;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dbcontext"></param>
        public unitofwork(tdbcontext dbcontext)
        {
            _dbcontext = dbcontext;
        }

        /// <summary>
        /// 保存
        /// </summary>
        public int savechanges()
        {
            int code;
            try
            {
                code = _dbcontext.savechanges();
            }
            catch (dbupdateexception e)
            {
                throw new exception(e.innerexception == null ? e.message : e.innerexception.message);
            }
            return code;
        }
    }
}

uow依赖注入

因为adddbcontext默认生命周期是scoped,所以用addscoped注册uow,确保每次请求共用同一个dbcontex对象。

            //注入dbcontext
            services.adddbcontext<mydbcontext> (options => options.usesqlserver(connectionstr,e => e.migrationsassembly("netcorewebapi.model")));
            //注入uow依赖
            services.addscoped<iunitofwork, unitofwork<mydbcontext>>();

使用uow

修改userrepository业务层

using netcorewebapi.model.models;
using netcorewebapi.repository.interface;
using netcorewebapi.repository.repository;
using system.collections.generic;
using system.linq;

namespace netcorewebapi.repository.implement
{
    /// <summary>
    /// 业务处理
    /// </summary>
    public class userrepository : iuserrepository
    {
        private readonly iunitofwork _unitofwork;
        private readonly irepository<tbuser> _userrepository;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userrepository"></param>
        /// <param name="unitofwork"></param>
        public userrepository(irepository<tbuser> userrepository, iunitofwork unitofwork)
        {
            _userrepository = userrepository;
            _unitofwork = unitofwork;
        }
        /// <summary>
        /// 添加用户
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public void add(tbuser entity)
        {
            _userrepository.add(entity);
            _unitofwork.savechanges();
        }
        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public void remove(tbuser entity)
        {
            _userrepository.remove(entity);
            _unitofwork.savechanges();
        }
        /// <summary>
        /// 查询用户
        /// </summary>
        /// <returns></returns>
        public ilist<tbuser> getall()
        {
            return _userrepository.getall().tolist();
        }
    }
}

遇到多仓储持久化操作时,用构造函数依赖注入相应的仓储即可。