多种仓储模式
IBaseRepository + BaseRepository 模式(适用于小项目,扩展性差)
- IRepository接口包含了基本的CRUD操作,如果业务中还需要扩展其他操作,只需在IRepository接口中添加。
- Repository实现了IRepository接口。其中ISqlHelp接口包含获取数据库链接字符串的功能,_context为EF或EF Core类库。
- 优点是简单、快速,缺点是扩展性差且违反开放-关闭原则(Open-Close Principle)
IBaseRepository.cs
public interface IBaseRepository<T> where T : class, new()
{
T Create(T model);
T Update(T model);
T Query(Guid guid);
T Query(Espression<Func<T, bool>> expression);
int Delete(Guid guid);
int BatchDelete(IList<Guid> guids);
List<T> GetAll();
List<T> GetAll(Expression<Func<T, bool>> expression, Expression<Func<T, dynamic>> sortPredicate, SortOrder sortOrder, int skip, int take, out int total);
}
BaseRepository.cs
public class BaseRepository<T> : IBaseRepository<T> where T : class, new()
{
//数据上下文
internal DbContext _context;
public BaseRepository(DbContext context)
{
_context = context
}
public T Create(T model)
{
_context.Entry(model).State = EntityState.Added;
var createRowCount = _context.SaveChanges();
return createRowCount > 0 ? model : null;
}
public T Update(T model)
{
_context.Entry(model).State = EntityState.Modified;
var updateRowAcount = _context.SaveChanges();
return updateRowAcount > 0 ? model : null;
}
public T Query(Guid guid)
{
return _context.Set<T>().Find(guid);
}
public T Query(Expression<Func<T, bool>> expression)
{
return _context.Set<T>().FirstOrDefault(expression);
}
public int Delete(Guid guid)
{
var model = _context.Set<T>().Find(guid);
if (model == null)
{
throw new ArgumentOutOfRangeException(nameof(guid));
}
_context.Entry(model).State = EntityState.Deleted;
return _context.SaveChanges();
}
public int BatchDelete(IList<Guid> guids)
{
foreach (var item in guids)
{
var model = _context.Set<T>().Find(item);
_context.Entry(model).State = EntityState.Deleted;
}
return _context.SaveChanges();
}
public List<T> GetAll()
{
return _context.Set<T>().Where(q => true).ToList();
}
public List<T> GetAll(Expression<Func<T, bool>> expression, Expression<Func<T, dynamic>> sortPredicate, SortOrder sortOrder, int skip, int take, out int total)
{
total = _context.Set<T>().Where(expression).Count();
switch (sortOrder)
{
case SortOrder.Ascending:
return _context.Set<T>().Where(expression).OrderBy(sortPredicate).Skip(skip).Take(take).ToList();
case SortOrder.Descending:
return _context.Set<T>().Where(expression).OrderByDescending(sortPredicate).Skip(skip).Take(take).ToList();
}
throw new InvalidOperationException("分页查询必须指定排序字段和排序顺序。");
}
}
AdminServer.cs
public sealed class AdminServer
{
private readonly IBaseRepository<User> _adminRepository;
public AdminServer(IBaseRepository<User> adminRepository)
{
_adminRepository = adminRepository;
}
public void CreateUser()
{
var admin = new User();
_adminRepository.Create(admin);
}
}
IBaseRepository+BaseRepository+IRepository+Repository(可扩展性好,未处理并发)
将BaseRepository.cs的实现方法上加上virtual关键字,使方法可以重载,每添加一个实体,需要添加对应的接口和实现
BaseRepository.cs
public class BaseRepository<T> : IBaseRepository<T> where T : class, new()
{
//数据上下文
internal DbContext _context;
public BaseRepository(DbContext context)
{
_context = context
}
public virtual T Create(T model)
{
//略
}
public virtual T Update(T model)
{
//略
}
public virtual T Query(Guid guid)
{
//略
}
public virtual T Query(Expression<Func<T, bool>> expression)
{
//略
}
public virtual int Delete(Guid guid)
{
//略
}
public virtual int BatchDelete(IList<Guid> guids)
{
//略
}
public virtual List<T> GetAll()
{
//略
}
public virtual List<T> GetAll(Expression<Func<T, bool>> expression, Expression<Func<T, dynamic>> sortPredicate, SortOrder sortOrder, int skip, int take, out int total)
{
//略
}
}
IRepository.cs
public partial interface IAdminRepository : IBaseRepository<Admin>
{
bool IsExist(Admin admin);
}
public partial interface IUserRepository : IBaseRepository<User>
{
}
Repository.cs
public partial class AdminRepository : BaseRepository<Admin>,IAdminRepository
{
public AdminRepository(ISqlHelp sqlHelp) : base(sqlHelp)
{
}
public bool IsExist(Admin admin)
{
//略
}
}
public partial class UserRepository : BaseRepository<User>,IUserRepository
{
public UserRepository(ISqlHelp sqlHelp) : base(sqlHelp)
{
}
}
AdminServer.cs
public sealed class AdminServer
{
private readonly IAdminRepository _adminRepository;
public AdminServer(IAdminRepository adminRepository)
{
_adminRepository = adminRepository;
}
public void CreateUser()
{
var admin = new User();
_adminRepository.Create(admin);
}
public bool IsExist(Admin admin)
{
return _adminRepository.IsExist(admin);
}
}
仓储模式+工作单元模式(扩展性高,有并发处理需求)
使用工作单元的原因是可以提高数据库写操作负载,并且在仓储模式中可以根据不同的数据库链接字符串读不同的库。
IUnitOfWork.cs
public interface IUnitOfWork : IDisposable
{
_context _context { get; set; }
/// <summary>
/// 提交所有更改
/// </summary>
Task CommitAsync();
#region Methods
/// <summary>
/// 将指定的聚合根标注为“新建”状态。
/// </summary>
/// <typeparam name="T">需要标注状态的聚合根类型。</typeparam>
/// <param name="obj">需要标注状态的聚合根。</param>
void RegisterNew<T>(T obj) where T : class, IEntity;
/// <summary>
/// 将指定的聚合根标注为“更改”状态。
/// </summary>
/// <typeparam name="T">需要标注状态的聚合根类型。</typeparam>
/// <param name="obj">需要标注状态的聚合根。</param>
void RegisterModified<T>(T obj) where T : class;
/// <summary>
/// 将指定的聚合根标注为“删除”状态。
/// </summary>
/// <typeparam name="T">需要标注状态的聚合根类型。</typeparam>
/// <param name="obj">需要标注状态的聚合根。</param>
void RegisterDeleted<T>(T obj) where T : class;
#endregion
}
UnitOfWork.cs
public class UnitOfWork : IUnitOfWork
{
public _context _context { get; set; }
public UnitOfWork(IContextHelper contextHelp)
{
_context = contextHelp._context;
}
private AdminRepository _adminRepository;
public AdminRepository AdminRepository
{
get
{
return _adminRepository ?? new AdminRepository(_context);
}
}
public virtual async Task CommitAsync()
{
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
ex.Entries.Single().Reload();
}
}
public virtual void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!disposing)
{
return;
}
if (_context == null)
{
return;
}
_context.Dispose();
_context = null;
}
public virtual void RegisterNew<TEntity>(TEntity obj) where TEntity : class, IEntity
{
_context.Set<TEntity>().Add(obj);
}
public virtual void RegisterModified<TEntity>(TEntity obj) where TEntity : class
{
_context.Entry(obj).State = EntityState.Modified;
}
public virtual void RegisterDeleted<TEntity>(TEntity obj) where TEntity : class
{
_context.Entry(obj).State = EntityState.Deleted;
}
}
AdminServer.cs
public class AdminServer
{
private UnitOfWork unit;
public AdminServer(UnitOfWork unitOfWork)
{
unit = unitOfWork;
}
public IEnumerable Get()
{
return unit.AdminRepository.GetAll();
}
}