ASP.NET Core 中的 ORM 之 Entity Framework (7)

在 EF Core 中 DBContext 已经实现了工作单元模式,同时也比较容易更换统一的数据存储介质(通过支持的数据库驱动)。那么还有没有必要在 EF Core 上面再封装一层实现自己的仓储和工作单元呢?

如果项目比较简单,业务逻辑并不复杂。特别是在实现一些微服务的时候,每个项目(服务)都只负责一部分小的并且功能内聚的业务。这个时候或许保持代码简单***,没有必要过度设计。

当然,如果项目比较复杂,没有采用微服务架构而是多个模块都在一起的单体架构,可能同时需要多种数据存储介质和途径,用到了多种的数据访问和持久化技术,那么可能就需要好好设计一个适合项目的仓储和工作单元模式了。

下面实现一个简单的仓储和工作单元模式:

定义实体基类

public abstract class BaseEntity<TKey> { public virtual TKey Id { get; set; } }

定义仓储基类

public interface IRepository<TDbContext, TEntity, TKey> where TEntity : BaseEntity<TKey> where TDbContext : DbContext { Task<TEntity> GetByKeyAsync(TKey id); Task<IList<TEntity>> GetAsync( Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, List<Expression<Func<TEntity, object>>> includes = null); Task<TEntity> AddAsync(TEntity entity); TEntity Update(TEntity entity); void Delete(TKey id); void Delete(TEntity entity); } public class EFRepository<TDbContext, TEntity, TKey> : IRepository<TDbContext, TEntity, TKey> where TEntity : BaseEntity<TKey> where TDbContext : DbContext { protected readonly TDbContext _context; protected readonly DbSet<TEntity> dbSet; public EFRepository(TDbContext context) { this._context = context; this.dbSet = context.Set<TEntity>(); } public virtual async Task<TEntity> GetByKeyAsync(TKey id) { return await dbSet.FindAsync(id); } public virtual async Task<IList<TEntity>> GetAsync( Expression<Func<TEntity, bool>> predicate = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, List<Expression<Func<TEntity, object>>> includes = null) { IQueryable<TEntity> query = dbSet; if (includes != null) { query = includes.Aggregate(query, (current, include) => current.Include(include)); } if (orderBy != null) { query = orderBy(query); } if (predicate != null) { query = query.Where(predicate); } return await query.ToListAsync(); } public virtual async Task<TEntity> AddAsync(TEntity entity) { var result = await dbSet.AddAsync(entity); return result.Entity; } public virtual TEntity Update(TEntity entity) { AttachIfNot(entity); this._context.Entry(entity).State = EntityState.Modified; return entity; } public virtual void Delete(TKey id) { TEntity entity = dbSet.Find(id); Delete(entity); } public virtual void Delete(TEntity entity) { AttachIfNot(entity); dbSet.Remove(entity); } protected virtual void AttachIfNot(TEntity entity) { if (this._context.Entry(entity).State == EntityState.Detached) { dbSet.Attach(entity); } } }

可以根据需求扩展更多的方法。

定义工作单元基类

public interface IUnitOfWork<TDbContext> where TDbContext : DbContext { Task<int> SaveChangesAsync(); } public class UnitOfWork<TDbContext> : IUnitOfWork<TDbContext> where TDbContext : DbContext { private readonly TDbContext _dbContext; public UnitOfWork(TDbContext context) { _dbContext = context ?? throw new ArgumentNullException(nameof(context)); } public async Task<int> SaveChangesAsync() { return await _dbContext.SaveChangesAsync(); } }

定义 BloggingContext 并定义基于 BloggingContext 的仓储基类和工作单元基类

public class BloggingContext : DbContext { public BloggingContext(DbContextOptions<BloggingContext> options) : base(options) { } public DbSet<Blog> Blogs { get; set; } public DbSet<Post> Posts { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.ApplyConfiguration(new BlogConfiguration()); modelBuilder.ApplyConfiguration(new PostConfiguration()); } } public interface IBlogggingRepositoryBase<TEntity, TKey> : IRepository<BloggingContext, TEntity, TKey> where TEntity : BaseEntity<TKey> { } public class BlogggingRepositoryBase<TEntity, TKey> : EFRepository<BloggingContext, TEntity, TKey>, IBlogggingRepositoryBase<TEntity, TKey> where TEntity : BaseEntity<TKey> { public BlogggingRepositoryBase(BloggingContext dbContext) : base(dbContext) { } } public class BloggingUnitOfWork : UnitOfWork<BloggingContext> { public BloggingUnitOfWork(BloggingContext dbContext) : base(dbContext) { } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zgffdz.html