public class Other : BaseEntity
{
public string Name{ get; set; }
}
public class OtherConfig : BaseConfig<Other>
{
public override void Configure(EntityTypeBuilder<Other> builder)
{
builder.Property(a => a.Name).IsRequired();
base.Configure(builder);
}
}
public interface IUnitOfWork : IDisposable
{
Task<bool> SaveAsync();
Task BeginTransactionAsync();
Task<bool> CommitTransactionAsync();
}
public class UnitOfWork : IUnitOfWork
{
private readonly DbContext _context;
private IDbContextTransaction _transaction;
public UnitOfWork(DbContext context)
{
_context = context;
}
public async Task<bool> SaveAsync()
{
return await _context.SaveChangesAsync() >= 0;
}
public async Task BeginTransactionAsync()
{
_transaction = await _context.Database.BeginTransactionAsync();
}
public async Task<bool> CommitTransactionAsync()
{
try
{
var result = await _context.SaveChangesAsync() >= 0;
await _transaction.CommitAsync();
return result;
}
catch
{
await _transaction.RollbackAsync();
return false;
}
finally
{
_transaction.Dispose();
}
}
public void Dispose()
{
_context?.Dispose();
_transaction?.Dispose();
}
}
public interface IBaseRepository<TEntity> where TEntity : BaseEntity
{
public Task<List<TEntity>> FindAsync(
Expression<Func<TEntity, bool>>[] filters,
string orderBy,
int skip,
int limit);
public Task<List<TEntity>> FindAsync(
Expression<Func<TEntity, bool>>[] filters,
string orderBy);
public Task<List<TDto>> FindAsync<TDto>(
Expression<Func<TEntity, bool>>[] filters,
string orderBy);
public Task<List<TDto>> FindAsync<TDto>(
Expression<Func<TEntity, bool>>[] filters,
string orderBy,
int skip,
int limit);
public Task<int> CountAsync(
Expression<Func<TEntity, bool>>[] filters);
public Task<bool> IsAlreadyExistAsync(
Expression<Func<TEntity, bool>>[] filters);
public Task<bool> IsAlreadyExistAsync(Guid systemId);
public Task<bool> IsAlreadyExistAsync(IEnumerable<Guid> systemIds);
public Task<FindResult<TEntity>> FindResultAsync(
Expression<Func<TEntity, bool>>[] filters,
string orderBy,
int skip,
int limit);
public Task<FindResult<TDto>> FindResultAsync<TDto>(
Expression<Func<TEntity, bool>>[] filters,
string orderBy,
int skip,
int limit);
public Task<TEntity> FindOneAsync(Guid systemId);
public Task<TDto> FindOneAsync<TDto>(Guid systemId);
public Task<TEntity> FindOneAsync(Expression<Func<TEntity, bool>>[] filters,
string orderBy = null);
public Task<TDto> FindOneAsync<TDto>(Expression<Func<TEntity, bool>>[] filters,
string orderBy = null);
public Task<bool> InsertAsync(TEntity entity, Guid? creatorId, DateTime? now = null, bool isTesting = false);
public Task<bool> InsertAsync(IEnumerable<TEntity> entities, Guid? creatorId, DateTime? now = null,
bool isTesting = false);
public Task<bool> UpdateAsync(TEntity entity, Guid? editorId, DateTime? now = null, bool isTesting = false);
public Task<bool> UpdateAsync(IEnumerable<TEntity> entities, Guid? editorId, DateTime? now = null,
bool isTesting = false);
public Task<bool> DeleteAsync(TEntity entity, Guid? deleterId, DateTime? now = null, bool isTesting = false);
public Task<bool> DeleteAsync(IEnumerable<TEntity> entities, Guid? deleterId, DateTime? now = null,
bool isTesting = false);
}
public class BaseRepository<TEntity> : IBaseRepository<TEntity> where TEntity : BaseEntity
{
private readonly DbSet<TEntity> _dbSet;
private readonly IUnitOfWork _unitOfWork;
public BaseRepository(DbContext dbContext)
{
_dbSet = dbContext.Set<TEntity>();
_unitOfWork = new UnitOfWork(dbContext);
}
public async Task<List<TEntity>> FindAsync(Expression<Func<TEntity, bool>>[] filters, string orderBy, int skip,
int limit)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
if (!string.IsNullOrEmpty(orderBy))
query = OrderBy(query, orderBy);
if (skip > 0)
query = query.Skip(skip);
if (limit > 0)
query = query.Take(limit);
return await query.ToListAsync();
}
public async Task<List<TEntity>> FindAsync(Expression<Func<TEntity, bool>>[] filters, string orderBy)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
if (!string.IsNullOrEmpty(orderBy))
query = OrderBy(query, orderBy);
return await query.ToListAsync();
}
public async Task<List<TDto>> FindAsync<TDto>(Expression<Func<TEntity, bool>>[] filters, string orderBy)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
if (!string.IsNullOrEmpty(orderBy))
query = OrderBy(query, orderBy);
var result = await query.ToListAsync();
return result.ProjectTo<TEntity, TDto>();
}
public async Task<List<TDto>> FindAsync<TDto>(Expression<Func<TEntity, bool>>[] filters, string orderBy, int skip,
int limit)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
if (!string.IsNullOrEmpty(orderBy))
query = OrderBy(query, orderBy);
if (skip > 0)
query = query.Skip(skip);
if (limit > 0)
query = query.Take(limit);
var result = await query.ToListAsync();
return result.ProjectTo<TEntity, TDto>();
}
public async Task<int> CountAsync(Expression<Func<TEntity, bool>>[] filters)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
return await query.CountAsync();
}
public async Task<bool> IsAlreadyExistAsync(Expression<Func<TEntity, bool>>[] filters)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
return await query.AnyAsync();
}
public async Task<bool> IsAlreadyExistAsync(Guid systemId)
{
return await _dbSet.FirstOrDefaultAsync(x => x.Id == systemId && !x.IsDeleted) != null;
}
public async Task<bool> IsAlreadyExistAsync(IEnumerable<Guid> systemIds)
{
return await _dbSet.CountAsync(x => !x.IsDeleted && systemIds.Contains(x.Id)) == systemIds.Count();
}
public async Task<FindResult<TEntity>> FindResultAsync(Expression<Func<TEntity, bool>>[] filters, string orderBy,
int skip, int limit)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
if (!string.IsNullOrEmpty(orderBy))
query = OrderBy(query, orderBy);
var totalCount = await query.LongCountAsync();
if (skip > 0)
query = query.Skip(skip);
if (limit > 0)
query = query.Take(limit);
var items = await query.ToListAsync();
return FindResult<TEntity>.Success(items, totalCount);
}
public async Task<FindResult<TDto>> FindResultAsync<TDto>(Expression<Func<TEntity, bool>>[] filters, string orderBy,
int skip, int limit)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
if (!string.IsNullOrEmpty(orderBy))
query = OrderBy(query, orderBy);
var totalCount = await query.LongCountAsync();
if (skip > 0)
query = query.Skip(skip);
if (limit > 0)
query = query.Take(limit);
var result = await query.ToListAsync();
return FindResult<TDto>.Success(result.ProjectTo<TEntity, TDto>(), totalCount);
}
public async Task<TEntity> FindOneAsync(Guid systemId)
{
return await _dbSet.FirstOrDefaultAsync(x => x.Id == systemId && !x.IsDeleted);
}
public async Task<TDto> FindOneAsync<TDto>(Guid systemId)
{
var a = await _dbSet.FirstOrDefaultAsync(x => x.Id == systemId && !x.IsDeleted);
return a.ProjectTo<TEntity, TDto>();
}
public async Task<TEntity> FindOneAsync(Expression<Func<TEntity, bool>>[] filters, string orderBy = null)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
if (!string.IsNullOrEmpty(orderBy))
query = OrderBy(query, orderBy);
return await query.FirstOrDefaultAsync();
}
public async Task<TDto> FindOneAsync<TDto>(Expression<Func<TEntity, bool>>[] filters, string orderBy = null)
{
IQueryable<TEntity> query = _dbSet;
query = query.Where(x => !x.IsDeleted);
if (filters != null && filters.Any())
query = filters.Aggregate(query, (current, filter) => current.Where(filter));
if (!string.IsNullOrEmpty(orderBy))
query = OrderBy(query, orderBy);
var result = await query.FirstOrDefaultAsync();
return result.ProjectTo<TEntity, TDto>();
}
public async Task<bool> InsertAsync(TEntity entity, Guid? creatorId, DateTime? now = null, bool isTesting = false)
{
await _unitOfWork.BeginTransactionAsync();
now ??= DateTime.UtcNow;
entity.CreatedAt = now.Value;
entity.EditedAt = now.Value;
entity.CreatorId = creatorId;
entity.EditorId = creatorId;
entity.IsTesting = isTesting;
await _dbSet.AddAsync(entity);
await _unitOfWork.SaveAsync();
return await _unitOfWork.CommitTransactionAsync();
}
public async Task<bool> InsertAsync(IEnumerable<TEntity> entities, Guid? creatorId, DateTime? now = null,
bool isTesting = false)
{
await _unitOfWork.BeginTransactionAsync();
now ??= DateTime.UtcNow;
entities = entities.Select(x =>
{
x.CreatedAt = now.Value;
x.EditedAt = now.Value;
x.CreatorId = creatorId;
x.EditorId = creatorId;
x.IsTesting = isTesting;
return x;
});
await _dbSet.AddRangeAsync(entities);
await _unitOfWork.SaveAsync();
return await _unitOfWork.CommitTransactionAsync();
}
public async Task<bool> UpdateAsync(TEntity entity, Guid? editorId, DateTime? now = null, bool isTesting = false)
{
await _unitOfWork.BeginTransactionAsync();
now ??= DateTime.UtcNow;
entity.EditedAt = now.Value;
entity.EditorId = editorId;
entity.IsTesting = isTesting;
_dbSet.Entry(entity).State = EntityState.Modified;
await _unitOfWork.SaveAsync();
return await _unitOfWork.CommitTransactionAsync();
}
public async Task<bool> UpdateAsync(IEnumerable<TEntity> entities, Guid? editorId, DateTime? now = null,
bool isTesting = false)
{
await _unitOfWork.BeginTransactionAsync();
now ??= DateTime.UtcNow;
entities = entities.Select(x =>
{
x.EditedAt = now.Value;
x.EditorId = editorId;
x.IsTesting = isTesting;
return x;
});
foreach (var entity in entities)
{
_dbSet.Entry(entity).State = EntityState.Modified;
}
await _unitOfWork.SaveAsync();
return await _unitOfWork.CommitTransactionAsync();
}
public async Task<bool> DeleteAsync(TEntity entity, Guid? deleterId, DateTime? now = null, bool isTesting = false)
{
await _unitOfWork.BeginTransactionAsync();
now ??= DateTime.UtcNow;
entity.DeletedAt = now.Value;
entity.DeleterId = deleterId;
entity.IsDeleted = true;
entity.IsTesting = isTesting;
_dbSet.Entry(entity).State = EntityState.Modified;
await _unitOfWork.SaveAsync();
return await _unitOfWork.CommitTransactionAsync();
}
public async Task<bool> DeleteAsync(IEnumerable<TEntity> entities, Guid? deleterId, DateTime? now = null,
bool isTesting = false)
{
await _unitOfWork.BeginTransactionAsync();
now ??= DateTime.UtcNow;
entities = entities.Select(x =>
{
x.DeletedAt = now.Value;
x.DeleterId = deleterId;
x.IsDeleted = true;
x.IsTesting = isTesting;
return x;
});
foreach (var entity in entities)
{
_dbSet.Entry(entity).State = EntityState.Modified;
}
await _unitOfWork.SaveAsync();
return await _unitOfWork.CommitTransactionAsync();
}
private static IQueryable<TEntity> OrderBy(IQueryable<TEntity> query, string orderBy)
{
var propertyName = orderBy.Split(" ")[0];
query = orderBy.Contains("desc")
? query.OrderByDescending(x => EF.Property<TEntity>(x, propertyName))
: query.OrderBy(x => EF.Property<TEntity>(x, propertyName));
return query;
}
}