using System.Application.Entities; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; namespace System.Application.Repositories { /// /// 仓储接口定义 /// public interface IRepository { protected static async Task OperateRangeAsync( IEnumerable entities, Func> operate) => (await Task.WhenAll(entities.Select(operate))).Sum(); protected static async IAsyncEnumerable<(int rowCount, T entity)> OperateRangeAsyncEnumerable( IEnumerable entities, Func> operate) { foreach (var entity in entities) { var rowCount = await operate(entity); yield return (rowCount, entity); } } protected static async IAsyncEnumerable<(int rowCount, DbRowExecResult result, T entity)> OperateRangeAsyncEnumerable( IEnumerable entities, Func> operate) { foreach (var entity in entities) { var (rowCount, logic) = await operate(entity); yield return (rowCount, logic, entity); } } } /// public interface IRepository : IRepository where TEntity : class { #region 增(Insert Funs) 立即执行并返回受影响的行数 /// /// 将实体插入到数据库中 /// /// 要添加的实体 /// 受影响的行数 Task InsertAsync(TEntity entity); /// /// 将多个实体插入到数据库中 /// /// 要添加的多个实体 /// 受影响的行数 public Task InsertRangeAsync(IEnumerable entities) => OperateRangeAsync(entities, InsertAsync); /// public Task InsertRangeAsync(params TEntity[] entities) => InsertRangeAsync(entities.AsEnumerable()); #endregion #region 删(Delete Funs) 立即执行并返回受影响的行数 /// /// 将实体从数据库中删除 /// /// 要删除的实体 /// 受影响的行数 Task DeleteAsync(TEntity entity); /// /// 将多个实体从数据库中删除 /// /// 要删除的多个实体 /// 受影响的行数 public Task DeleteRangeAsync(IEnumerable entities) => OperateRangeAsync(entities, DeleteAsync); /// public Task DeleteRangeAsync(params TEntity[] entities) => DeleteRangeAsync(entities.AsEnumerable()); #endregion #region 改(Update Funs) 立即执行并返回受影响的行数 /// /// 将实体更新到数据库中 /// /// 要更新的实体 /// 受影响的行数 Task UpdateAsync(TEntity entity); /// /// 将多个实体更新到数据库中 /// /// 要更新的多个实体 /// 受影响的行数 public Task UpdateRangeAsync(IEnumerable entities) => OperateRangeAsync(entities, UpdateAsync); /// public Task UpdateRangeAsync(params TEntity[] entities) => UpdateRangeAsync(entities.AsEnumerable()); #endregion #region 查(通用查询) /// /// 返回序列中满足指定的条件或默认值,如果找到这样的元素的第一个元素 /// /// 用于测试每个元素是否满足条件的函数 /// /// default(TEntity) 如果 集合 为空,或者如果没有元素通过由指定的测试 ; /// 否则为中的第一个元素 集合 通过由指定的测试 /// /// /// 集合 或 为 /// Task FirstOrDefaultAsync(Expression> predicate); #endregion } /// public interface IRepository : IRepository, IGetPrimaryKey where TEntity : class, IEntity where TPrimaryKey : IEquatable { protected static bool IsDefault(TPrimaryKey primaryKey) { if (primaryKey == null) return true; // null is default TPrimaryKey defPrimaryKey = default; if (defPrimaryKey == null) return false; // primaryKey not null return EqualityComparer.Default.Equals(primaryKey, defPrimaryKey); } protected static Expression> LambdaEqualId(TPrimaryKey primaryKey) { var parameter = Expression.Parameter(typeof(TEntity)); var left = Expression.PropertyOrField(parameter, nameof(IEntity.Id)); var right = Expression.Constant(primaryKey, typeof(TPrimaryKey)); var body = Expression.Equal(left, right); return Expression.Lambda>(body, parameter); } #region 删(Delete Funs) 立即执行并返回受影响的行数 /// /// 根据主键将实体从数据库中删除 /// /// 要删除的实体主键 /// 受影响的行数 Task DeleteAsync(TPrimaryKey primaryKey); /// /// 根据主键将多个实体从数据库中删除 /// /// 要删除的多个实体主键 /// 受影响的行数 public Task DeleteRangeAsync(IEnumerable primaryKeys) => OperateRangeAsync(primaryKeys, DeleteAsync); /// public Task DeleteRangeAsync(params TPrimaryKey[] primaryKeys) => DeleteRangeAsync(primaryKeys.AsEnumerable()); /// public IAsyncEnumerable<(int rowCount, TPrimaryKey entity)> DeleteRangeAsyncEnumerable(IEnumerable primaryKeys) => OperateRangeAsyncEnumerable(primaryKeys, DeleteAsync); /// public IAsyncEnumerable<(int rowCount, TPrimaryKey entity)> DeleteRangeAsyncEnumerable(params TPrimaryKey[] primaryKeys) => DeleteRangeAsyncEnumerable(primaryKeys.AsEnumerable()); #endregion #region 查(通用查询) /// /// 根据主键查询实体 /// /// 要查询的实体主键 /// 查询到的实体 ValueTask FindAsync(TPrimaryKey primaryKey); /// /// 判断实体是否已经存在 /// /// 要查询的实体 /// 要查询的实体主键 /// 实体是否存在数据库中 public async ValueTask ExistAsync(TPrimaryKey primaryKey) { var entity = await FindAsync(primaryKey); return entity != null; } /// public ValueTask ExistAsync(TEntity entity) { var primaryKey = GetPrimaryKey(entity); return ExistAsync(primaryKey); } #endregion #region 增或改(InsertOrUpdate Funs) 立即执行并返回受影响的行数 /// /// 新增或更新实体 /// /// 要新增或更新的实体 /// 受影响的行数与数据库逻辑 public async Task<(int rowCount, DbRowExecResult result)> InsertOrUpdateAsync(TEntity entity) { var exist = await ExistAsync(entity); int rowCount; DbRowExecResult result; if (exist) { rowCount = await UpdateAsync(entity); result = DbRowExecResult.Update; } else { rowCount = await InsertAsync(entity); result = DbRowExecResult.Insert; } return (rowCount, result); } /// /// 批量新增或更新实体 /// /// 要新增或更新的多个实体 /// public IAsyncEnumerable<(int rowCount, DbRowExecResult result, TEntity entity)> InsertOrUpdateAsync(IEnumerable entities) => OperateRangeAsyncEnumerable(entities, InsertOrUpdateAsync); /// public IAsyncEnumerable<(int rowCount, DbRowExecResult result, TEntity entity)> InsertOrUpdateAsync(params TEntity[] entities) => InsertOrUpdateAsync(entities.AsEnumerable()); #endregion } }