基于.Net6平台,EFCore+Dapper 封装Repository,实现UnitOfWork,提供基本的CURD操作,支持多数据库,多DbContext
Nuget引用包:Wei.Repository
- 定义实体类
publicclassUser{// 字段名为Id时,可省略主键标记//[Key]publicstringId{get;set;}publicstringName{get;set;}}
- 自定义DbContext,需要继承BaseDbContext
publicclassUserDbContext:BaseDbContext{publicDemoDbContext(DbContextOptions<UserDbContext>options):base(options){}publicDbSet<User>User{get;set;}}
- 注入服务,添加Repository组件
builder.Services.AddRepository<UserDbContext>(ops=>ops.UseSqlite("Data Source=user.db"));// Mysql,SqlServer 可以安装驱动后自行测试,demo暂只用sqllite测试//builder.Services.AddRepository<UserDbContext>(ops => ops.UseMysql("xxx"));//builder.Services.AddRepository<UserDbContext>(ops =>ops.UseSqlServer("xxx"));
- 【可选】自定义Repository,实现自己的业务逻辑,如果只是简单的crud,可以直接用泛型Repository
// 如果只有一个DbContext,可以不用指定UserDbContext类型// public class UserRepository : Repository<User>, IUserRepositorypublicclassUserRepository:Repository<UserDbContext,User>,IUserRepository{publicUserRepository(DbContextFactorydbContextFactory):base(dbContextFactory){}// 重写基类新增方法,实现自己的业务逻辑publicoverrideTask<User>InsertAsync(Userentity,CancellationTokencancellationToken=default){entity.Id=Guid.NewGuid().ToString();returnbase.InsertAsync(entity,cancellationToken);}}publicinterfaceIUserRepository:IRepository<UserDbContext,User>{}
- 在Controller中使用
publicclassUserController:ControllerBase{//自定义仓储privatereadonlyIUserRepository_userRepository;// 工作单元,// 如果不传入指定DbContext,默认使用第一个注入的DbContextprivatereadonlyIUnitOfWork<UserDbContext>_unitOfWork;publicUserController(IUserRepositoryuserRepository,IUnitOfWork<UserDbContext>unitOfWork){_userRepository=userRepository;_unitOfWork=unitOfWork;}[HttpPost]publicasyncTask<User>InsertAsync(stringname,CancellationTokencancellationToken){varentity=await_userRepository.InsertAsync(newUser{Name=name},cancellationToken);_unitOfWork.SaveChanges();returnentity;}}
1. 泛型IRepository接口
#region Query// 查询IQueryable<TEntity>Query();IQueryable<TEntity>Query(Expression<Func<TEntity,bool>>predicate);IQueryable<TEntity>QueryNoTracking();IQueryable<TEntity>QueryNoTracking(Expression<Func<TEntity,bool>>predicate);// 根据主键获取(支持复合主键)TEntityGet(paramsobject[]id);ValueTask<TEntity>GetAsync(paramsobject[]id);ValueTask<TEntity>GetAsync(object[]ids,CancellationTokencancellationToken);// 获取所有IEnumerable<TEntity>GetAll();Task<IEnumerable<TEntity>>GetAllAsync(CancellationTokencancellationToken=default);IEnumerable<TEntity>GetAll(Expression<Func<TEntity,bool>>predicate);Task<IEnumerable<TEntity>>GetAllAsync(Expression<Func<TEntity,bool>>predicate,CancellationTokencancellationToken=default);// 获取第一个或默认值TEntityFirstOrDefault();Task<TEntity>FirstOrDefaultAsync(CancellationTokencancellationToken=default);TEntityFirstOrDefault(Expression<Func<TEntity,bool>>predicate);Task<TEntity>FirstOrDefaultAsync(Expression<Func<TEntity,bool>>predicate,CancellationTokencancellationToken=default); #endregion #region Insert// 新增TEntityInsert(TEntityentity);Task<TEntity>InsertAsync(TEntityentity,CancellationTokencancellationToken=default);// 批量新增voidInsert(IEnumerable<TEntity>entities);TaskInsertAsync(IEnumerable<TEntity>entities,CancellationTokencancellationToken=default); #endregion Insert #region Update// 更新TEntityUpdate(TEntityentity);// 批量更新voidUpdate(IEnumerable<TEntity>entities);// 根据表达式条件更新指定字段IEnumerable<TEntity>Update(Expression<Func<TEntity,bool>>predicate,Action<TEntity>updateAction);Task<IEnumerable<TEntity>>UpdateAsync(Expression<Func<TEntity,bool>>predicate,Action<TEntity>updateAction,CancellationTokencancellationToken=default); #endregion Update #region Delete// 删除voidDelete(TEntityentity);// 根据主键(支持复合主键)删除voidDelete(paramsobject[]id);// 根据表达式条件批量删除voidDelete(Expression<Func<TEntity,bool>>predicate); #endregion #region AggregateboolAny();Task<bool>AnyAsync(CancellationTokencancellationToken=default);boolAny(Expression<Func<TEntity,bool>>predicate);Task<bool>AnyAsync(Expression<Func<TEntity,bool>>predicate,CancellationTokencancellationToken=default);intCount();Task<int>CountAsync(CancellationTokencancellationToken=default);intCount(Expression<Func<TEntity,bool>>predicate);Task<int>CountAsync(Expression<Func<TEntity,bool>>predicate,CancellationTokencancellationToken=default); #endregion
2. IUnitOfWork 工作单元接口
// 获取 DbContextpublicDbContextDbContext{get;}IDbConnectionGetConnection();// 工作单元 提交intSaveChanges();Task<int>SaveChangesAsync(CancellationTokencancellationToken=default);// Dapper 封装Task<IEnumerable<TEntity>>QueryAsync<TEntity>(stringsql,objectparam=null,IDbContextTransactiontrans=null)whereTEntity:class;Task<int>ExecuteAsync(stringsql,objectparam,IDbContextTransactiontrans=null);// 开启事务IDbContextTransactionBeginTransaction();publicIDbContextTransactionBeginTransaction(IsolationLevelisolationLevel);publicTask<IDbContextTransaction>BeginTransactionAsync(CancellationTokencancellationToken=default);publicTask<IDbContextTransaction>BeginTransactionAsync(IsolationLevelisolationLevel,CancellationTokencancellationToken=default);
3. Dapper事务
publicasyncTaskInsertWithTransaction(Useruser1,Useruser2){usingvartran=_unitOfWork.BeginTransaction();try{await_unitOfWork.ExecuteAsync("INSERT INTO User (Id,Name) VALUES ('1','张三'",user1,tran);await_unitOfWork.ExecuteAsync("INSERT INTO User (Id,Name) VALUES ('2','李四'",user2,tran);// 提交事务tran.Commit();}catch(Exceptione){// 异常回归事务tran.Rollback();}}
4. EF+Dapper混合事务
publicasyncTaskInsertWithTransaction(Useruser1,Useruser2){usingvartran=_unitOfWork.BeginTransaction();try{await_userRepository.InsertAsync(user1);await_unitOfWork.SaveChangesAsync();await_unitOfWork.ExecuteAsync("INSERT INTO User (Id,Name) VALUES ('2','李四'",user2,tran);// 提交事务tran.Commit();}catch(Exceptione){// 异常回归事务tran.Rollback();}}
5.服务自动注入
实现了三种服务类型注入
- SingletonServiceAttribute
- ScopedServiceAttribute
- TransientServiceAttribute
[ScopedService]publicclassBookService:IBookService{}publicinterfaceIBookService{}
需要在服务注入是调用配置特性服务注入
// 自动注入服务builder.Services.ConfigureAttributeServices();
6.其他
支持多数据库连接,多个DbContext,具体请查看Demo