仓储模式作为领域驱动设计(Domain-Driven Design,DDD)的一部分,在系统设计中的使用非常广泛。它主要用于解除业务逻辑层与数据访问层之间的耦合,使业务逻辑层在存储、访问数据库时无须关心数据的来源及存储方式,仓储模式带来的好处是一套代码可以适用于多个类,提高代码复用。
话不多说,上代码
1.新建一个仓储接口IRepository
public interface IRepository<T> where T:class
{
/// <summary>
/// 添加
/// </summary>
/// <param name="entity">数据实体</param>
/// <returns>添加后的数据实体</returns>
T Add(T entity);
/// <summary>
/// 添加
/// </summary>
/// <param name="entity">数据实体</param>
/// <returns>成功/失败</returns>
bool AddOk(T entity);
/// <summary>
/// 更新
/// </summary>
/// <param name="entity">数据实体</param>
/// <returns>更新后的数据实体</returns>
T Update(T entity);
/// <summary>
/// 更新
/// </summary>
/// <param name="entity">数据实体</param>
/// <returns>成功/失败</returns>
bool UpdateOk(T entity);
/// <summary>
/// 删除
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
bool Delete(int id);
/// <summary>
/// id查询
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
T SelectById(int id);
/// <summary>
/// 条件查询返回单个实体
/// </summary>
/// <param name="whereLambda">查询条件</param>
/// <returns></returns>
T SelectWhere(Expression<Func<T,bool>> whereLambda);
/// <summary>
/// 查询全部
/// </summary>
/// <returns>集合</returns>
List<T> SelectAll();
/// <summary>
/// 条件查询返回实体集合
/// </summary>
/// <param name="anyLambda">查询条件</param>
/// <returns>集合</returns>
List<T> SelectList(Expression<Func<T,bool>> whereLambda);
/// /// <summary>
/// 条件查询且排序
/// </summary>
/// <typeparam name="TOrder">排序字段的类型</typeparam>
/// <param name="whereLambda">查询条件</param>
/// <param name="isAsc">是否升序</param>
/// <param name="orderbyLambda">排序条件</param>
/// <returns></returns>
List<T> SelectList<TOrder>(Expression<Func<T,bool>> whereLambda,bool isAsc,Expression<Func<T, TOrder>> orderbyLambda);
/// <summary>
/// 分页条件查询且排序
/// </summary>
/// <typeparam name="TOrder">排序字段的类型</typeparam>
/// <param name="page">分页参数</param>
/// <param name="whereLambda">查询条件</param>
/// <param name="orderbyLambda">排序条件</param>
/// <param name="isAsc">是否升序</param>
/// <returns>分页后的结果</returns>
PageData<T> SelectPageList<TOrder>(PagePara page, Expression<Func<T, bool>> whereLambda=null, Expression<Func<T, TOrder>> orderbyLambda=null, bool isAsc=false);
}
2.建一个实现类Repository
public class Repository<T> : IRepository<T> where T:class
{
public reflectionContext db = new reflectionContext();
#region 添加
public T Add(T entity)
{
db.Set<T>().Add(entity);
db.SaveChanges();
return entity;
}
public bool AddOk(T entity)
{
db.Set<T>().Add(entity);
return db.SaveChanges() > 0;
}
#endregion
#region 删除
public bool Delete(int id)
{
var entity = db.Set<T>().Find(id);
db.Set<T>().Remove(entity);
return db.SaveChanges() > 0;
}
#endregion
#region 查询
public T SelectById(int id)
{
return db.Set<T>().Find(id);
}
public T SelectWhere(Expression<Func<T, bool>> whereLambda)
{
//.AsNoTracking()非追踪查询
//针对查询,在一些情况下,我们只需要返回一个只读的数据就可以,并不会对数据记录进行任何的修改。这种时候不希望Entity Framework进行不必要的状态变动跟踪,
//可以使用Entity Framework的AsNoTracking方法来查询返回不带变动跟踪的查询结果。
//由于是无变动跟踪,所以对返回的数据的没有进行任何修改,在SaveChanges()时,都不会提交到数据库中。
return db.Set<T>().AsNoTracking().FirstOrDefault(whereLambda);
}
public List<T> SelectList(Expression<Func<T, bool>> whereLambda)
{
return db.Set<T>().AsNoTracking().Where(whereLambda).ToList();
}
public List<T> SelectAll()
{
return db.Set<T>().AsNoTracking().ToList();
}
public List<T> SelectList<TOrder>(Expression<Func<T, bool>> whereLambda, bool isAsc, Expression<Func<T, TOrder>> orderbyLambda)
{
var list = db.Set<T>().AsNoTracking().Where(whereLambda);
if (isAsc)
list = list.OrderBy<T, TOrder>(orderbyLambda);
else
list = list.OrderByDescending<T, TOrder>(orderbyLambda);
return list.ToList();
}
public PageData<T> SelectPageList<TOrder>(PagePara page, Expression<Func<T, bool>> whereLambda=null, Expression<Func<T, TOrder>> orderbyLambda=null, bool isAsc=false)
{
var list = db.Set<T>().AsNoTracking();
if (whereLambda!=null)
{
list = list.Where(whereLambda);
}
if (orderbyLambda!=null)
{
if(isAsc)
list = list.OrderBy<T, TOrder>(orderbyLambda);
else
list = list.OrderByDescending<T, TOrder>(orderbyLambda);
}
PageData<T> pageData = new PageData<T>();
pageData.PageIndex = page.PageIndex;
pageData.PageSize = page.PageSize;
pageData.Count = list.Count();
pageData.ListData = list.Skip((page.PageIndex - 1) * page.PageSize).Take(page.PageSize).ToList();
return pageData;
}
#endregion
#region 修改
public T Update(T entity)
{
db.Set<T>().Attach(entity).State = EntityState.Modified;
db.SaveChanges();
return entity;
}
public bool UpdateOk(T entity)
{
db.Set<T>().Attach(entity).State = EntityState.Modified;
return db.SaveChanges() > 0;
}
#endregion
}
其中的分页参数类PagePara和结果类PageData分别如下
/// <summary>
/// 分页参数类
/// </summary>
public class PagePara
{
public int PageIndex { get; set; }
public int PageSize { get; set; }
}
public class PageData<T>:PagePara
{
public int Count { get; set; }
public int PageCount { get => Convert.ToInt32(Math.Ceiling(Count /(double) PageSize)); }
public List<T> ListData { get; set; }
}
然后附上使用方式吧,只需要将泛型替换掉就可以实现仓储的复用了。
static void Main(string[] args)
{
IRepository<Student> repository = new Repository<Student>();
//新增
Console.WriteLine("---------------------新增----------------------");
Student stu = new Student() {Name = "test1",Age = 33,Likeinfo = "hap"};
stu= repository.Add(stu);
Console.WriteLine(stu.Id);
//修改
Console.WriteLine("---------------------修改----------------------");
stu.Name = "TEST2";
stu = repository.Update(stu);
Console.WriteLine(stu.Name);
//删除
//repository.Delete(stu.Id);
//id查询
Console.WriteLine("---------------------id查询----------------------");
Student student = repository.SelectById(1);
Console.WriteLine(student.Name);
//条件查询
Console.WriteLine("---------------------条件查询----------------------");
student = repository.SelectWhere(n => n.Name == "小黑");
Console.WriteLine(student.Name);
//查询全部
Console.WriteLine("---------------------查询全部----------------------");
var stuList = repository.SelectAll();
Console.WriteLine(JsonConvert.SerializeObject(stuList));
//条件查询排序
Console.WriteLine("---------------------条件查询,排序----------------------");
stuList = repository.SelectList(x => x.Name.Contains("小"),false,x=>x.Age);
Console.WriteLine(JsonConvert.SerializeObject(stuList));
//条件分页查询
Console.WriteLine("---------------------条件分页查询----------------------");
PagePara pagePara = new PagePara { PageIndex = 1, PageSize = 2 };
var pageData = repository.SelectPageList<Student>(pagePara);
Console.WriteLine(JsonConvert.SerializeObject(pageData));
}
后来改良版:
实体接口
/// <summary>
/// 实体基类接口
/// </summary>
/// <typeparam name="TPrimaryKey">主键</typeparam>
public interface IEntity<TPrimaryKey>
{
TPrimaryKey Id { get; set; }
}
public interface IEntity : IEntity<int>
{
}
仓储接口
public interface IRepository<TEntity, in TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{
#region 查询
/// <summary>
/// 获取用于从整个表中检索实体的IQueryable
/// </summary>
/// <returns>可用于从数据库中选择实体</returns>
IQueryable<TEntity> GetAll();
/// <summary>
/// 用于获取所有实体
/// </summary>
/// <returns>所有实体列表</returns>
List<TEntity> GetAllList();
/// <summary>
/// 用于获取所有实体的异步实现
/// </summary>
/// <returns>所有实体列表</returns>
Task<List<TEntity>> GetAllListAsync();
/// <summary>
/// 用于获取传入本方法的所有实体
/// </summary>
/// <param name="predicate">筛选实体的条件</param>
/// <returns>所有实体列表</returns>
List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 用于获取传入本方法的所有实体
/// </summary>
/// <param name="predicate">筛选实体的条件</param>
/// <returns>所有实体列表</returns>
Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 通过传入的筛选条件来获取实体信息
/// 如果查询不到返回值,则会引发异常
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
TEntity Single(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 通过传入的筛选条件来获取实体信息
/// 如果查询不到返回值,则会引发异常
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 通过传入的筛选条件查询实体信息,如果没有找到,则返回null
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 通过传入的筛选条件查询实体信息,如果没有找到,则返回null
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 根据实体的主键查询
/// </summary>
/// <param name="id">主键</param>
/// <returns></returns>
TEntity FindById(TPrimaryKey id);
/// <summary>
/// 根据实体的主键查询异步实现
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<TEntity> FindByIdAsync(TPrimaryKey id);
#endregion
#region 添加
/// <summary>
/// 添加一个新实体
/// </summary>
/// <param name="entity">被添加的实体</param>
/// <returns></returns>
TEntity Insert(TEntity entity);
/// <summary>
/// 添加一个新实体
/// </summary>
/// <param name="entity">被添加的实体</param>
/// <returns></returns>
Task<TEntity> InsertAsync(TEntity entity);
#endregion
#region 修改
/// <summary>
/// 更新现有实体
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
TEntity Update(TEntity entity);
/// <summary>
/// 更新现有实体
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
Task<TEntity> UpdateAsync(TEntity entity);
#endregion
#region 删除
/// <summary>
/// 删除一个实体
/// </summary>
/// <param name="entity">无返回值</param>
void Delete(TEntity entity);
/// <summary>
/// 删除一个实体
/// </summary>
/// <param name="entity">无返回值</param>
/// <returns></returns>
Task DeleteAsync(TEntity entity);
/// <summary>
/// 传入的条件可删除多个实体
/// 注意:所有符合给定条件的实体都将被检索和删除
/// 如果条件比较多,则待删除的实体也比较多,则可能会导致主要的性能问题
/// </summary>
/// <param name="predicate"></param>
void Delete(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 传入的条件可删除多个实体
/// 注意:所有符合给定条件的实体都将被检索和删除
/// 如果条件比较多,则待删除的实体也比较多,则可能会导致主要的性能问题
/// </summary>
/// <param name="predicate"></param>
Task DeleteAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 按id删除
/// </summary>
/// <param name="id"></param>
void Delete(TPrimaryKey id);
/// <summary>
/// 按id删除的异步实现
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task DeleteAsync(TPrimaryKey id);
#endregion
#region 总和计算
/// <summary>
/// 获取此仓储中所有实体的总和
/// </summary>
/// <returns>实体的总数</returns>
int Count();
/// <summary>
/// 获取此仓储中所有实体的总和
/// </summary>
/// <returns>实体的总数</returns>
Task<int> CountAsync();
/// <summary>
/// 支持条件筛选计算仓储中的实体总和
/// </summary>
/// <param name="predicate"></param>
/// <returns>实体的总数</returns>
int Count(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 支持条件筛选计算仓储中的实体总和
/// </summary>
/// <param name="predicate"></param>
/// <returns>实体的总数</returns>
Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 获取此存储库中所有的实体的总和,如果返回值大于了Int.MaxValue值,则推荐该方法
/// </summary>
/// <returns>实体的总和</returns>
long LongCount();
/// <summary>
/// 获取此存储库中所有的实体的总和,如果返回值大于了Int.MaxValue值,则推荐该方法
/// </summary>
/// <returns>实体的总和</returns>
Task<long> LongCountAsync();
/// <summary>
/// 获取此存储库中所有的实体的总和,如果返回值大于了Int.MaxValue值,则推荐该方法
/// </summary>
/// <returns>实体的总和</returns>
long LongCount(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 获取此存储库中所有的实体的总和,如果返回值大于了Int.MaxValue值,则推荐该方法
/// </summary>
/// <returns>实体的总和</returns>
Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate);
#endregion
}
仓储实现
public class Repository<TEntity, TPrimaryKey> : IRepository<TEntity, TPrimaryKey> where TEntity : class,IEntity<TPrimaryKey>
{
/// <summary>
/// 数据库上下文
/// </summary>
private readonly xxxDbContext _db;
/// <summary>
/// 通过泛型,从数据库上下文中获取领域模型
/// </summary>
public virtual DbSet<TEntity> Table => _db.Set<TEntity>();
protected EfRepositoryBase(TDbContext db)
{
_db = db;
}
protected void Save()
{
_db.SaveChanges();
}
/// <summary>
/// 检查实体是否处于跟踪状态,如果是,则返回;如果不是,则添加跟踪状态
/// </summary>
/// <param name="entity"></param>
protected virtual void AttachIfNot(TEntity entity)
{
var entry = _db.ChangeTracker.Entries().FirstOrDefault(ent => ent.Entity == entity);
if (entry != null)
{
return;
}
Table.Attach(entity);
}
protected async Task SaveAsync()
{
await _db.SaveChangesAsync();
}
public IQueryable<TEntity> GetAll()
{
return Table.AsQueryable();
}
public List<TEntity> GetAllList()
{
return GetAll().ToList();
}
public async Task<List<TEntity>> GetAllListAsync()
{
return await GetAll().ToListAsync();
}
public List<TEntity> GetAllList(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().Where(predicate).ToList();
}
public async Task<List<TEntity>> GetAllListAsync(Expression<Func<TEntity, bool>> predicate)
{
return await GetAll().Where(predicate).ToListAsync();
}
public TEntity Single(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().Single(predicate);
}
public async Task<TEntity> SingleAsync(Expression<Func<TEntity, bool>> predicate)
{
return await GetAll().SingleAsync(predicate);
}
public TEntity FirstOrDefault(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().FirstOrDefault(predicate);
}
public async Task<TEntity> FirstOrDefaultAsync(Expression<Func<TEntity, bool>> predicate)
{
return await GetAll().FirstOrDefaultAsync(predicate);
}
public TEntity Insert(TEntity entity)
{
var newEntity = Table.Add(entity).Entity;
Save();
return newEntity;
}
public async Task<TEntity> InsertAsync(TEntity entity)
{
var newEntity = (await Table.AddAsync(entity)).Entity;
await SaveAsync();
return newEntity;
}
public TEntity Update(TEntity entity)
{
AttachIfNot(entity);
_db.Entry(entity).State = EntityState.Modified;
Save();
return entity;
}
public async Task<TEntity> UpdateAsync(TEntity entity)
{
AttachIfNot(entity);
_db.Entry(entity).State = EntityState.Modified;
await SaveAsync();
return entity;
}
public void Delete(TEntity entity)
{
AttachIfNot(entity);
Table.Remove(entity);
Save();
}
public async Task DeleteAsync(TEntity entity)
{
AttachIfNot(entity);
Table.Remove(entity);
await SaveAsync();
}
public void Delete(Expression<Func<TEntity, bool>> predicate)
{
foreach (var entity in GetAll().Where(predicate).ToList())
{
Delete(entity);
}
}
public async Task DeleteAsync(Expression<Func<TEntity, bool>> predicate)
{
foreach (var entity in GetAll().Where(predicate).ToList())
{
await DeleteAsync(entity);
}
}
public int Count()
{
return GetAll().Count();
}
public async Task<int> CountAsync()
{
return await GetAll().CountAsync();
}
public int Count(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().Where(predicate).Count();
}
public async Task<int> CountAsync(Expression<Func<TEntity, bool>> predicate)
{
return await GetAll().Where(predicate).CountAsync();
}
public long LongCount()
{
return GetAll().LongCount();
}
public async Task<long> LongCountAsync()
{
return await GetAll().LongCountAsync();
}
public long LongCount(Expression<Func<TEntity, bool>> predicate)
{
return GetAll().Where(predicate).LongCount();
}
public async Task<long> LongCountAsync(Expression<Func<TEntity, bool>> predicate)
{
return await GetAll().Where(predicate).LongCountAsync();
}
public TEntity FindById(TPrimaryKey id)
{
return Table.Find(id);
}
public async Task<TEntity> FindByIdAsync(TPrimaryKey id)
{
return await Table.FindAsync(id);
}
public void Delete(TPrimaryKey id)
{
var entity = FindById(id);
AttachIfNot(entity);
Table.Remove(entity);
Save();
}
public async Task DeleteAsync(TPrimaryKey id)
{
var entity = await FindByIdAsync(id);
AttachIfNot(entity);
Table.Remove(entity);
await SaveAsync();
}
}
需要源码的可以加.net core学习交流群:831181779,在群里@群主即可