前边说了abp vnext实现增删改查,框架自带的仓储能实现我们大部分的需求了。但是在修改数据的时候有时会遇到一种情况,就是我们只希望更新部分字段,而且牵扯到排他锁的问题,这时用框架自带的修改方法就有点牵强了。
这样我们就需要实现自定义仓储了,官方说明文档里给了两种自定义仓储的方法:
1、针对某个实体的service来自定义仓储
2、设置整体的默认仓储类
这两个有各自的优缺点:
1、针对实体的service来自定义仓储 优点就是可以增加方法,比如增加一个按照字段修改的方法UpdateFieldAsync,可以根据实体的实际需求个性化定制。但是缺点是没法通用。只能在这个实体的service用,每个都要单独定制。
2、默认的通用仓储的默认实现是EfCoreRepository类,你可以创建自己的实现,并将其做为默认实现,这是他的优点,就是可以通用。但是缺点就是只能重写现有的方法,不能新加方法。这是我目前了解到的,不知道是否可以新增加方法,如果有,可以留言里跟我说。
现在就这两种自定义仓储分别说下实现方法
1、针对某个实体的service来自定义仓储
讲这个的时候就说下我实现了自定义的修改部分字段的方法如何实现的。
1)、定义仓储接口
public interface ICustomExtendRepository:IRepository<Category,Guid> { Task UpdateFieldAsync(Category model, bool autoSave, params string[] fieldNames); }
2)、实现这个接口
public class CustomExtendRepository: EfCoreRepository<SoftwarePortalDbContext, Category, Guid>, ICustomExtendRepository { public CustomExtendRepository(IDbContextProvider<SoftwarePortalDbContext> dbContextProvider) : base(dbContextProvider) { } public async Task UpdateFieldAsync(Category model, bool autoSave, params string[] fieldNames) { DbContext.Entry<Category>(model).SetModify(fieldNames); if (autoSave) { await DbContext.SaveChangesAsync(); } } }
public static void SetModify<T>(this EntityEntry<T> entry, params string[] fieldNames) where T : class { if (entry.State == EntityState.Detached) { entry.State = EntityState.Unchanged; } fieldNames?.ForEach(fieldName => { entry.Property(fieldName).IsModified = true; }); }
3)、然后注入
注入方法是 options.AddRepository<Category, CustomExtendRepository>();注意,仍可以注入使用默认通用仓储
完整代码如下:
public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext<SoftwarePortalDbContext>(options => { /* Add custom repositories here. Example: * options.AddRepository<Question, EfCoreQuestionRepository>(); */ options.AddDefaultRepositories(true); options.AddRepository<Category, CustomExtendRepository>(); }); }
以上实现可以做到不用先查询出来实体才能做修改。可以直接做到修改。
2、设置整体的默认仓储类
1)、定义仓储类
public class CustomDefaultRepositoryBase<TEntity>: EfCoreRepository<SoftwarePortalDbContext, TEntity>where TEntity : class, IEntity { public CustomDefaultRepositoryBase(IDbContextProvider<SoftwarePortalDbContext> dbContextProvider) : base(dbContextProvider) { } } public class CustomDefaultRepositoryBase<TEntity, TKey>: EfCoreRepository<SoftwarePortalDbContext, TEntity, TKey>where TEntity : class, IEntity<TKey> { public CustomDefaultRepositoryBase(IDbContextProvider<SoftwarePortalDbContext> dbContextProvider) : base(dbContextProvider) { } }
2)、第一个用于具有复合主键的实体,第二个用于具有单个主键的实体
建议从EfCoreRepository类继承并在需要时重写方法. 否则,你需要手动实现所有标准仓储方法.
现在,你可以使用
SetDefaultRepositoryClasses Options,如下实现
public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext<SoftwarePortalDbContext>(options => { /* Add custom repositories here. Example: * options.AddRepository<Question, EfCoreQuestionRepository>(); */ options.AddDefaultRepositories(true); options.SetDefaultRepositoryClasses( typeof(CustomDefaultRepositoryBase<,>), typeof(CustomDefaultRepositoryBase<>) ); }); }
这个默认的我没有做任何方法的重写。如果需要有自定义,可以自行重写相应的方法。
自定义仓储这样就说完了。有什么问题,评论区交流
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!