namespace HrynCo.DAL.EF.Core; using System.Diagnostics.CodeAnalysis; using System.Linq.Expressions; using HrynCo.DAL.Abstract.Entities; using Microsoft.EntityFrameworkCore; [SuppressMessage("Major Code Smell", "S2436:Reduce the number of generic parameters", Justification = "Generic design is intentional and improves reusability")] public abstract class BaseEfRepository : IEfRepository where TEntity : class, IEntity where TDbContext : DbContext where TEntityId : struct { protected BaseEfRepository(TDbContext dbContext) { DbContext = dbContext; DbSet = DbContext.Set(); } public TDbContext DbContext { get; } private DbSet DbSet { get; } public TEntity Add(TEntity entity, bool save = true) { var entityEntry = DbSet.Add(entity); TEntity addedEntity = entityEntry.Entity; if (save) { DbContext.SaveChanges(); } return addedEntity; } public void Add(TEntity[] entities, bool save = true) { foreach (TEntity entity in entities) { Add(entity, save); } } public async Task AddAsync(TEntity entity, bool save = true) { var entityEntry = await DbSet.AddAsync(entity); TEntity addedEntity = entityEntry.Entity; if (save) { await DbContext.SaveChangesAsync(); } return addedEntity; } public void Delete(IEnumerable id) { foreach (TEntityId entityId in id) { Delete([GetById(entityId)!]); } } public void Delete(TEntityId id) { Delete([id]); } public virtual void Delete(TEntity[] entities) { DoRemove(entities); DbContext.SaveChanges(); } public void Delete(TEntity entity) { DoRemove(entity); DbContext.SaveChanges(); } public async Task DeleteAsync(TEntityId id) { Delete(id); await DbContext.SaveChangesAsync(); } public async Task DeleteAsync(IEnumerable id) { foreach (TEntityId entityId in id) { await DeleteAsync(entityId); } } public async Task DeleteAsync(TEntity entity) { DoRemove(entity); await DbContext.SaveChangesAsync(); } public virtual async Task GetByIdAsync(TEntityId id) { TEntity? entity = await DbSet.FindAsync(id); return entity; } public async Task UpdateAsync(TEntity entity, bool save = true) { DbSet.Attach(entity); DbContext.Entry(entity).State = EntityState.Modified; if (save) { await DbContext.SaveChangesAsync(); } } public virtual void Update(TEntity entity, bool save = true) { DbSet.Attach(entity); DbContext.Entry(entity).State = EntityState.Modified; if (save) { DbContext.SaveChanges(); } } public async Task SaveChangesAsync() { await DbContext.SaveChangesAsync(); } public IQueryable Get( Expression>? filter = null, Func, IOrderedQueryable>? orderBy = null, string includeProperties = "") { IQueryable query = DbContext.Set(); if (filter != null) { query = query.Where(filter); } if (!string.IsNullOrWhiteSpace(includeProperties)) { foreach (string includeProperty in includeProperties.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) { query = query.Include(includeProperty); } } if (orderBy != null) { return orderBy(query).AsQueryable(); } return query.AsQueryable(); } public virtual IQueryable GetAll() { return DbContext.Set().AsQueryable(); } public void RemoveRange(IEnumerable entities) { DbContext.Set().RemoveRange(entities); } public void Remove(TEntity entity) { DbContext.Set().Remove(entity); } public async Task> GetAllAsync() { return await DbContext.Set().ToListAsync(); } public async Task Exists(TEntityId id) { return await DbContext.Set().AnyAsync(e => e.Id.Equals(id)); } public virtual TEntity? GetById(TEntityId id) { return DbContext.Set().Find(id); } public void ClearChangeTracker() { DbContext.ChangeTracker.Clear(); } protected virtual void DoRemove(TEntity[] entities) { foreach (TEntity entity in entities) { DoRemove(entity); } } protected virtual void DoRemove(TEntity entity) { DbSet.Remove(entity); } }