Files
hrynco-ef/HrynCo.DAL.EF/Core/BaseEfRepository.cs
T
Anatolii Grynchuk 15c58522ef feat: rebuild base repository hierarchy, add readme and agents
- replace EfRepository/BaseDbContext/UtcValueConverter with BaseEfRepository and BaseRepository
- add IEfRepository interface hierarchy
- consolidate IEntity into Entity.cs, remove standalone IEntity.cs
- add PagedResult
- adjust all namespaces to HrynCo.DAL.Abstract / HrynCo.DAL.EF
- add README.md with solution overview, versioning rules, class diagram
- add AGENTS.md

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-05-06 01:15:59 +03:00

219 lines
5.1 KiB
C#

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<TDbContext, TEntity, TEntityId> :
IEfRepository<TEntity, TEntityId>
where TEntity : class, IEntity<TEntityId>
where TDbContext : DbContext
where TEntityId : struct
{
protected BaseEfRepository(TDbContext dbContext)
{
DbContext = dbContext;
DbSet = DbContext.Set<TEntity>();
}
public TDbContext DbContext { get; }
private DbSet<TEntity> 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<TEntity> 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<TEntityId> 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<TEntityId> id)
{
foreach (TEntityId entityId in id)
{
await DeleteAsync(entityId);
}
}
public async Task DeleteAsync(TEntity entity)
{
DoRemove(entity);
await DbContext.SaveChangesAsync();
}
public virtual async Task<TEntity?> 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<TEntity> Get(
Expression<Func<TEntity, bool>>? filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>? orderBy = null,
string includeProperties = "")
{
IQueryable<TEntity> query = DbContext.Set<TEntity>();
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<TEntity> GetAll()
{
return DbContext.Set<TEntity>().AsQueryable();
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
DbContext.Set<TEntity>().RemoveRange(entities);
}
public void Remove(TEntity entity)
{
DbContext.Set<TEntity>().Remove(entity);
}
public async Task<List<TEntity>> GetAllAsync()
{
return await DbContext.Set<TEntity>().ToListAsync();
}
public async Task<bool> Exists(TEntityId id)
{
return await DbContext.Set<TEntity>().AnyAsync(e => e.Id.Equals(id));
}
public virtual TEntity? GetById(TEntityId id)
{
return DbContext.Set<TEntity>().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);
}
}