首次接触仓储的概念来自Eric Evans 的经典著作《领域驱动设计-软件核心复杂性应对之道》,但书中没有具体实现。如何实现仓储模式,在我这几年的使用过程中也积累了一些具体的实施经验。根据项目的大小、可维护性、可扩展性,以及并发我们可以做以下几种设计;
1、项目小,扩展性差
public interface IRepository<T> where T : class,new() { /// <summary> /// 创建对象 /// </summary> /// <param name="model"></param> /// <returns></returns> T Create(T model); /// <summary> /// 更新对象 /// </summary> /// <param name="model"></param> /// <returns></returns> T Update(T model); /// <summary> /// 根据对象全局唯一标识检索对象 /// </summary> /// <param name="guid"></param> /// <returns></returns> T Retrieve(Guid guid); /// <summary> /// 根据条件表达式检索对象 /// </summary> /// <param name="expression">条件表达式</param> /// <returns></returns> /// <exception cref = "ArgumentNullException" > source 为 null</exception> T Retrieve(Expression<Func<T, bool>> expression); /// <summary> /// 根据对象全局唯一标识删除对象 /// </summary> /// <param name="guid">对象全局唯一标识</param> /// <returns>删除的对象数量</returns> int Delete(Guid guid); /// <summary> /// 根据对象全局唯一标识集合删除对象集合 /// </summary> /// <param name="guids">全局唯一标识集合</param> /// <returns>删除的对象数量</returns> 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); }
IRepository接口包含了CRUD操作,如果在业务中还需要扩展,只需在IRepository接口中添加即可。
public class RepositoryImpl<T> : IRepository<T> where T : class, new() { protected readonly string ConnectionString; protected RepositoryImpl(ISqlHelp sqlHelp) { ConnectionString = sqlHelp.SQLConnectionString(); } public int BatchDelete(IList<Guid> guids) { using (var dbcontext = new DbContext(ConnectionString)) { foreach (var item in guids) { var model = dbcontext.Set<T>().Find(item); dbcontext.Entry(model).State = EntityState.Deleted; } return dbcontext.SaveChanges(); } } public T Create(T model) { using (var dbcontext = new DbContext(ConnectionString)) { dbcontext.Entry(model).State = EntityState.Added; var createRowCount = dbcontext.SaveChanges(); return createRowCount > 0 ? model : null; } } /// <summary> /// 删除模型 /// </summary> /// <param name="guid">指定的全局标识</param> /// <returns>删除数量</returns> /// <exception cref="ArgumentOutOfRangeException"></exception> public int Delete(Guid guid) { using (var dbcontext = new DbContext(ConnectionString)) { var model = dbcontext.Set<T>().Find(guid); if (model == null) throw new ArgumentOutOfRangeException(nameof(guid)); dbcontext.Entry(model).State = EntityState.Deleted; return dbcontext.SaveChanges(); } } public List<T> GetAll() { using (var dbcontext = new DbContext(ConnectionString)) { ret