Refactor repository pattern and modernize codebase
Removed `SaveChangesAsync` from `IRepository` and `Repository` to centralize transaction management in `DbContext`. Updated `CfgProfileRepository` to use `Context` property instead of `_context`. Refactored `Repository` class to use C# 9.0 record-like constructor syntax and replaced private fields with properties (`Context`, `DbSet`, `Mapper`). Replaced `Any()` with `Count == 0` for null checks and updated `FindAsync` to use C# 11 object array syntax. Added conditional compilation for framework-specific differences. These changes improve readability, consistency, and leverage modern C# features.
This commit is contained in:
@@ -90,10 +90,5 @@ namespace ECMJobRunner.Domain.Interfaces
|
|||||||
/// <param name="cancellationToken">Cancellation token</param>
|
/// <param name="cancellationToken">Cancellation token</param>
|
||||||
/// <returns>True if entity was found and deleted, false otherwise</returns>
|
/// <returns>True if entity was found and deleted, false otherwise</returns>
|
||||||
Task<bool> DeleteSingleAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
|
Task<bool> DeleteSingleAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Save all changes asynchronously
|
|
||||||
/// </summary>
|
|
||||||
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ namespace ECMJobRunner.Infrastructure.Repositories
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<CfgProfile?> GetByIdWithSqlJobsAsync(long id, CancellationToken cancellationToken = default)
|
public async Task<CfgProfile?> GetByIdWithSqlJobsAsync(long id, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return await _context.CfgProfiles
|
return await Context.CfgProfiles
|
||||||
.Include(p => p.SqlJobs)
|
.Include(p => p.SqlJobs)
|
||||||
.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
|
.FirstOrDefaultAsync(p => p.Id == id, cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -41,7 +41,7 @@ namespace ECMJobRunner.Infrastructure.Repositories
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<List<CfgProfile>> GetAllActiveWithSqlJobsAsync(CancellationToken cancellationToken = default)
|
public async Task<List<CfgProfile>> GetAllActiveWithSqlJobsAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return await _context.CfgProfiles
|
return await Context.CfgProfiles
|
||||||
.Include(p => p.SqlJobs)
|
.Include(p => p.SqlJobs)
|
||||||
.Where(p => p.Active)
|
.Where(p => p.Active)
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|||||||
@@ -20,145 +20,144 @@ namespace ECMJobRunner.Infrastructure.Repositories
|
|||||||
/// Uses AutoMapper for DTO mapping
|
/// Uses AutoMapper for DTO mapping
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="TEntity">Entity type</typeparam>
|
/// <typeparam name="TEntity">Entity type</typeparam>
|
||||||
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
|
/// <remarks>
|
||||||
|
/// Constructor
|
||||||
|
/// </remarks>
|
||||||
|
public class Repository<TEntity>(JobRunnerDbContext context, IMapper mapper) : IRepository<TEntity> where TEntity : class
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Database context
|
/// Database context
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly JobRunnerDbContext _context;
|
protected readonly JobRunnerDbContext Context = context ?? throw new ArgumentNullException(nameof(context));
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// DbSet for the entity
|
/// DbSet for the entity
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly DbSet<TEntity> _dbSet;
|
protected readonly DbSet<TEntity> DbSet = context.Set<TEntity>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// AutoMapper instance for DTO mapping
|
/// AutoMapper instance for DTO mapping
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly IMapper _mapper;
|
protected readonly IMapper Mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Constructor
|
|
||||||
/// </summary>
|
|
||||||
public Repository(JobRunnerDbContext context, IMapper mapper)
|
|
||||||
{
|
|
||||||
_context = context ?? throw new ArgumentNullException(nameof(context));
|
|
||||||
_mapper = mapper ?? throw new ArgumentNullException(nameof(mapper));
|
|
||||||
_dbSet = context.Set<TEntity>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<TEntity?> GetByIdAsync(long id, CancellationToken cancellationToken = default)
|
public virtual async Task<TEntity?> GetByIdAsync(long id, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
#if NET48
|
#if NET48
|
||||||
return await _dbSet.FindAsync(cancellationToken, id);
|
return await DbSet.FindAsync(cancellationToken, id);
|
||||||
#else
|
#else
|
||||||
return await _dbSet.FindAsync(new object[] { id }, cancellationToken);
|
return await DbSet.FindAsync([id], cancellationToken);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = default)
|
public virtual async Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return await _dbSet.ToListAsync(cancellationToken);
|
return await DbSet.ToListAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<IEnumerable<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
public virtual async Task<IEnumerable<TEntity>> FindAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return await _dbSet.Where(predicate).ToListAsync(cancellationToken);
|
return await DbSet.Where(predicate).ToListAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<TEntity?> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
public virtual async Task<TEntity?> SingleOrDefaultAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return await _dbSet.SingleOrDefaultAsync(predicate, cancellationToken);
|
return await DbSet.SingleOrDefaultAsync(predicate, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<TEntity> AddAsync<TDto>(TDto dto, CancellationToken cancellationToken = default) where TDto : class
|
public virtual async Task<TEntity> AddAsync<TDto>(TDto dto, CancellationToken cancellationToken = default) where TDto : class
|
||||||
{
|
{
|
||||||
|
#if NETFRAMEWORK
|
||||||
if (dto == null) throw new ArgumentNullException(nameof(dto));
|
if (dto == null) throw new ArgumentNullException(nameof(dto));
|
||||||
|
|
||||||
var entity = _mapper.Map<TEntity>(dto);
|
|
||||||
|
|
||||||
#if NET48
|
|
||||||
_dbSet.Add(entity);
|
|
||||||
await Task.CompletedTask;
|
|
||||||
#else
|
|
||||||
await _dbSet.AddAsync(entity, cancellationToken);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
await SaveChangesAsync(cancellationToken);
|
var entity = Mapper.Map<TEntity>(dto);
|
||||||
|
|
||||||
|
#if NET48
|
||||||
|
DbSet.Add(entity);
|
||||||
|
#else
|
||||||
|
await DbSet.AddAsync(entity, cancellationToken);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
await Context.SaveChangesAsync(cancellationToken);
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<int> AddRangeAsync<TDto>(IEnumerable<TDto> dtos, CancellationToken cancellationToken = default) where TDto : class
|
public virtual async Task<int> AddRangeAsync<TDto>(IEnumerable<TDto> dtos, CancellationToken cancellationToken = default) where TDto : class
|
||||||
{
|
{
|
||||||
|
#if NETFRAMEWORK
|
||||||
if (dtos == null) throw new ArgumentNullException(nameof(dtos));
|
if (dtos == null) throw new ArgumentNullException(nameof(dtos));
|
||||||
|
|
||||||
var dtoList = dtos.ToList();
|
|
||||||
if (!dtoList.Any())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
var entities = _mapper.Map<List<TEntity>>(dtoList);
|
|
||||||
|
|
||||||
#if NET48
|
|
||||||
_dbSet.AddRange(entities);
|
|
||||||
await Task.CompletedTask;
|
|
||||||
#else
|
|
||||||
await _dbSet.AddRangeAsync(entities, cancellationToken);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return await SaveChangesAsync(cancellationToken);
|
var dtoList = dtos.ToList();
|
||||||
|
if (dtoList.Count == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
var entities = Mapper.Map<List<TEntity>>(dtoList);
|
||||||
|
|
||||||
|
#if NET48
|
||||||
|
DbSet.AddRange(entities);
|
||||||
|
#else
|
||||||
|
await DbSet.AddRangeAsync(entities, cancellationToken);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return await Context.SaveChangesAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<int> UpdateAsync<TDto>(Expression<Func<TEntity, bool>> predicate, TDto dto, CancellationToken cancellationToken = default) where TDto : class
|
public virtual async Task<int> UpdateAsync<TDto>(Expression<Func<TEntity, bool>> predicate, TDto dto, CancellationToken cancellationToken = default) where TDto : class
|
||||||
{
|
{
|
||||||
|
#if NETFRAMEWORK
|
||||||
if (dto == null) throw new ArgumentNullException(nameof(dto));
|
if (dto == null) throw new ArgumentNullException(nameof(dto));
|
||||||
|
#endif
|
||||||
|
|
||||||
var entities = await _dbSet.Where(predicate).ToListAsync(cancellationToken);
|
var entities = await DbSet.Where(predicate).ToListAsync(cancellationToken);
|
||||||
|
|
||||||
if (!entities.Any())
|
if (entities.Count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
foreach (var entity in entities)
|
foreach (var entity in entities)
|
||||||
{
|
{
|
||||||
_mapper.Map(dto, entity);
|
Mapper.Map(dto, entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
return await SaveChangesAsync(cancellationToken);
|
return await Context.SaveChangesAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<bool> UpdateSingleAsync<TDto>(Expression<Func<TEntity, bool>> predicate, TDto dto, CancellationToken cancellationToken = default) where TDto : class
|
public virtual async Task<bool> UpdateSingleAsync<TDto>(Expression<Func<TEntity, bool>> predicate, TDto dto, CancellationToken cancellationToken = default) where TDto : class
|
||||||
{
|
{
|
||||||
|
#if NETFRAMEWORK
|
||||||
if (dto == null) throw new ArgumentNullException(nameof(dto));
|
if (dto == null) throw new ArgumentNullException(nameof(dto));
|
||||||
|
#endif
|
||||||
|
|
||||||
var entity = await SingleOrDefaultAsync(predicate, cancellationToken);
|
var entity = await SingleOrDefaultAsync(predicate, cancellationToken);
|
||||||
|
|
||||||
if (entity == null)
|
if (entity == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_mapper.Map(dto, entity);
|
Mapper.Map(dto, entity);
|
||||||
|
|
||||||
await SaveChangesAsync(cancellationToken);
|
await Context.SaveChangesAsync(cancellationToken);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public virtual async Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
public virtual async Task<int> DeleteAsync(Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var entities = await _dbSet.Where(predicate).ToListAsync(cancellationToken);
|
var entities = await DbSet.Where(predicate).ToListAsync(cancellationToken);
|
||||||
|
|
||||||
if (!entities.Any())
|
if (entities.Count == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
_dbSet.RemoveRange(entities);
|
DbSet.RemoveRange(entities);
|
||||||
|
|
||||||
return await SaveChangesAsync(cancellationToken);
|
return await Context.SaveChangesAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
@@ -169,20 +168,10 @@ namespace ECMJobRunner.Infrastructure.Repositories
|
|||||||
if (entity == null)
|
if (entity == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_dbSet.Remove(entity);
|
DbSet.Remove(entity);
|
||||||
|
|
||||||
await SaveChangesAsync(cancellationToken);
|
await Context.SaveChangesAsync(cancellationToken);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
|
||||||
public virtual async Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
|
|
||||||
{
|
|
||||||
#if NET48
|
|
||||||
return await _context.SaveChangesAsync();
|
|
||||||
#else
|
|
||||||
return await _context.SaveChangesAsync(cancellationToken);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user