From d16a4b6bb427137f114c207ed0e258622e8c0a77 Mon Sep 17 00:00:00 2001 From: TekH Date: Wed, 5 Nov 2025 14:20:12 +0100 Subject: [PATCH] refactor(repository): make UpdateAsync more flexible with Action - Introduced Action-based UpdateAsync method for more flexible updates - Updated TDto-based UpdateAsync to delegate to the new method - Reduced code duplication and Mapper dependency - Preserved existing Create, Read, and Delete functionality --- .../Repository/IRepository.cs | 71 +++++---- .../DbRepository.cs | 149 +++++++++--------- 2 files changed, 116 insertions(+), 104 deletions(-) diff --git a/DigitalData.Core.Abstraction.Application/Repository/IRepository.cs b/DigitalData.Core.Abstraction.Application/Repository/IRepository.cs index 27dd627..5433e71 100644 --- a/DigitalData.Core.Abstraction.Application/Repository/IRepository.cs +++ b/DigitalData.Core.Abstraction.Application/Repository/IRepository.cs @@ -1,5 +1,4 @@ -using DigitalData.Core.Abstractions.Interfaces; -using System.Linq.Expressions; +using System.Linq.Expressions; #if NETFRAMEWORK using System; using System.Collections.Generic; @@ -15,90 +14,100 @@ namespace DigitalData.Core.Abstraction.Application.Repository { #endif -public interface IRepository -{ - #region Create + public interface IRepository + { + #region Create +#if NET + public +#endif + Task CreateAsync(TEntity entity, CancellationToken cancel = default); + #if NET public #endif - Task CreateAsync(TEntity entity, CancellationToken cancel = default); + Task> CreateAsync(IEnumerable entities, CancellationToken cancel = default); #if NET public #endif - Task> CreateAsync(IEnumerable entities, CancellationToken cancel = default); + Task CreateAsync(TDto dto, CancellationToken cancel = default); #if NET public #endif - Task CreateAsync(TDto dto, CancellationToken cancel = default); + Task> CreateAsync(IEnumerable dtos, CancellationToken cancel = default); + #endregion Create + #region Read #if NET public #endif - Task> CreateAsync(IEnumerable dtos, CancellationToken cancel = default); - #endregion Create + IQueryable Query { get; } - #region Read #if NET public #endif - IQueryable Query { get; } + IQueryable Where(Expression> expression); #if NET public #endif - IQueryable Where(Expression> expression); + IEnumerable GetAll(); #if NET public #endif - IEnumerable GetAll(); + Task> GetAllAsync(CancellationToken cancel = default); + #endregion Read + #region Update #if NET public #endif - Task> GetAllAsync(CancellationToken cancel = default); - #endregion Read + Task UpdateAsync(TDto dto, Expression> expression, CancellationToken cancel = default); - #region Update #if NET public #endif - Task UpdateAsync(TDto dto, Expression> expression, CancellationToken cancel = default); + Task UpdateAsync(TDto dto, Func, IQueryable> query, CancellationToken cancel = default); #if NET public #endif - Task UpdateAsync(TDto dto, Func, IQueryable> query, CancellationToken cancel = default); - #endregion Update + Task UpdateAsync(Action modification, Func, IQueryable> query, CancellationToken cancel = default); - #region Delete #if NET public #endif - Task DeleteAsync(Expression> expression, CancellationToken cancel = default); + Task UpdateAsync(Action modification, Expression> expression, CancellationToken cancel = default); + #endregion Update + #region Delete #if NET public #endif - Task DeleteAsync(Func, IQueryable> query, CancellationToken cancel = default); - #endregion Delete + Task DeleteAsync(Expression> expression, CancellationToken cancel = default); - #region Obsolete - [Obsolete("Use CreateAsync, UpdateAsync or DeleteAsync")] #if NET public #endif - IQueryable Read(); + Task DeleteAsync(Func, IQueryable> query, CancellationToken cancel = default); + #endregion Delete - [Obsolete("Use IRepository.Where")] + #region Obsolete + [Obsolete("Use CreateAsync, UpdateAsync or DeleteAsync")] #if NET public #endif - IQueryable ReadOnly(); - #endregion -} + IQueryable Read(); + + [Obsolete("Use IRepository.Where")] +#if NET + public +#endif + IQueryable ReadOnly(); + #endregion + } #if NETFRAMEWORK } #endif \ No newline at end of file diff --git a/DigitalData.Core.Infrastructure/DbRepository.cs b/DigitalData.Core.Infrastructure/DbRepository.cs index fde9865..a0a2f42 100644 --- a/DigitalData.Core.Infrastructure/DbRepository.cs +++ b/DigitalData.Core.Infrastructure/DbRepository.cs @@ -21,114 +21,117 @@ namespace DigitalData.Core.Infrastructure { #endif -public class DbRepository : IRepository where TDbContext : DbContext where TEntity : class -{ - protected internal readonly TDbContext Context; + public class DbRepository : IRepository where TDbContext : DbContext where TEntity : class + { + protected internal readonly TDbContext Context; - protected internal readonly DbSet Entities; + protected internal readonly DbSet Entities; - public IMapper + public IMapper #if NET ? #endif - Mapper { get; } + Mapper { get; } - public DbRepository(TDbContext context, DbSetFactory factory, IMapper + public DbRepository(TDbContext context, DbSetFactory factory, IMapper #if NET ? #endif - mapper = null) - { - Context = context; - Entities = factory.Create(context); - Mapper = mapper; - } + mapper = null) + { + Context = context; + Entities = factory.Create(context); + Mapper = mapper; + } - #region Create - public virtual async Task CreateAsync(TEntity entity, CancellationToken cancel = default) - { - Entities.Add(entity); - await Context.SaveChangesAsync(cancel); - return entity; - } + #region Create + public virtual async Task CreateAsync(TEntity entity, CancellationToken cancel = default) + { + Entities.Add(entity); + await Context.SaveChangesAsync(cancel); + return entity; + } - public virtual async Task> CreateAsync(IEnumerable entities, CancellationToken cancel = default) - { - Entities.AddRange(entities); - await Context.SaveChangesAsync(cancel); - return entities; - } + public virtual async Task> CreateAsync(IEnumerable entities, CancellationToken cancel = default) + { + Entities.AddRange(entities); + await Context.SaveChangesAsync(cancel); + return entities; + } - public virtual Task CreateAsync(TDto dto, CancellationToken cancel = default) - => CreateAsync(Mapper + public virtual Task CreateAsync(TDto dto, CancellationToken cancel = default) + => CreateAsync(Mapper #if NET ! #endif - .Map(dto), cancel); + .Map(dto), cancel); - public virtual Task> CreateAsync(IEnumerable dtos, CancellationToken cancel = default) - => CreateAsync(Mapper + public virtual Task> CreateAsync(IEnumerable dtos, CancellationToken cancel = default) + => CreateAsync(Mapper #if NET ! #endif - .Map>(dtos), cancel); - #endregion Create - - #region Read - public virtual IQueryable Query => Entities.AsNoTracking(); + .Map>(dtos), cancel); + #endregion Create - public virtual IQueryable Where(Expression> expression) => Entities.AsNoTracking().Where(expression); + #region Read + public virtual IQueryable Query => Entities.AsNoTracking(); - public virtual IEnumerable GetAll() => Entities.AsNoTracking().ToList(); + public virtual IQueryable Where(Expression> expression) => Entities.AsNoTracking().Where(expression); - public virtual async Task> GetAllAsync(CancellationToken cancel = default) => await Entities.AsNoTracking().ToListAsync(cancel); - #endregion Read + public virtual IEnumerable GetAll() => Entities.AsNoTracking().ToList(); - #region Update - public virtual Task UpdateAsync(TDto dto, Expression> expression, CancellationToken cancel = default) => UpdateAsync(dto, q => q.Where(expression), cancel); + public virtual async Task> GetAllAsync(CancellationToken cancel = default) => await Entities.AsNoTracking().ToListAsync(cancel); + #endregion Read - public virtual async Task UpdateAsync(TDto dto, Func, IQueryable> query, CancellationToken cancel = default) - { - var entities = await query(Entities).ToListAsync(cancel); + #region Update + public virtual Task UpdateAsync(TDto dto, Expression> expression, CancellationToken cancel = default) => UpdateAsync(dto, q => q.Where(expression), cancel); - for (int i = entities.Count - 1; i >= 0; i--) - { - Mapper + public virtual Task UpdateAsync(TDto dto, Func, IQueryable> query, CancellationToken cancel = default) + => UpdateAsync(entity => Mapper #if NET - ! + ! #endif - .Map(dto, entities[i]); - Entities.Update(entities[i]); - } + .Map(dto, entity), query, cancel); - await Context.SaveChangesAsync(cancel); - } - #endregion Update + public virtual async Task UpdateAsync(Action modification, Func, IQueryable> query, CancellationToken cancel = default) + { + var entities = await query(Entities).ToListAsync(cancel); - #region Delete - public virtual Task DeleteAsync(Expression> expression, CancellationToken cancel = default) => DeleteAsync(q => q.Where(expression), cancel); + for (int i = entities.Count - 1; i >= 0; i--) + modification.Invoke(entities[i]); - public virtual async Task DeleteAsync(Func, IQueryable> query, CancellationToken cancel = default) - { - var entities = await query(Entities).ToListAsync(cancel); + await Context.SaveChangesAsync(cancel); + } - for (int i = entities.Count - 1; i >= 0; i--) + public virtual Task UpdateAsync(Action modification, Expression> expression, CancellationToken cancel = default) + => UpdateAsync(modification, q => q.Where(expression), cancel); + #endregion Update + + #region Delete + public virtual Task DeleteAsync(Expression> expression, CancellationToken cancel = default) => DeleteAsync(q => q.Where(expression), cancel); + + public virtual async Task DeleteAsync(Func, IQueryable> query, CancellationToken cancel = default) { - Entities.Remove(entities[i]); - } + var entities = await query(Entities).ToListAsync(cancel); - await Context.SaveChangesAsync(cancel); - } - #endregion Delete + for (int i = entities.Count - 1; i >= 0; i--) + { + Entities.Remove(entities[i]); + } - #region Obsolete - [Obsolete("Use IRepository.Where")] - public virtual IQueryable Read() => Entities.AsQueryable(); + await Context.SaveChangesAsync(cancel); + } + #endregion Delete + + #region Obsolete + [Obsolete("Use IRepository.Where")] + public virtual IQueryable Read() => Entities.AsQueryable(); - [Obsolete("Use IRepository.Get")] - public virtual IQueryable ReadOnly() => Entities.AsNoTracking(); - #endregion -} + [Obsolete("Use IRepository.Get")] + public virtual IQueryable ReadOnly() => Entities.AsNoTracking(); + #endregion + } #if NETFRAMEWORK } #endif \ No newline at end of file