Refactor solution structure and add RabbitMQ config
Reorganized the solution structure to align with a layered architecture: - Replaced `src` folder with `core`, `infrastructure`, and `presentation`. - Moved projects to their respective folders. - Added `DigitalData.MessagingService.Publisher.Abstraction` project. - Removed `DigitalData.MessagingService.Client` project. Updated project configurations and nesting in the solution file. Added `appsettings.Secrets.json` with RabbitMQ and email account settings: - RabbitMQ configuration includes hostname, port, credentials, and queue/exchange details. - Email configuration includes SMTP server details and credentials.
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
using System.Linq.Expressions;
|
||||
using AutoMapper;
|
||||
using DigitalData.MessagingService.Application.Common.Interfaces;
|
||||
using DigitalData.MessagingService.Domain.Exceptions;
|
||||
using DigitalData.MessagingService.Infrastructure.Persistence;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DigitalData.MessagingService.Infrastructure.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// Generic repository implementation with AutoMapper-based CRUD operations.
|
||||
/// IMPORTANT: Each operation auto-saves changes - NO explicit SaveChangesAsync needed!
|
||||
/// </summary>
|
||||
public class Repository<TEntity>(MessagingServiceDbContext Context, IMapper Mapper) : IRepository<TEntity> where TEntity : class
|
||||
{
|
||||
private readonly DbSet<TEntity> _dbSet = Context.Set<TEntity>();
|
||||
|
||||
// --- CREATE ---
|
||||
|
||||
public async Task<TEntity> CreateAsync<TDto>(TDto dto, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = Mapper.Map<TEntity>(dto);
|
||||
await _dbSet.AddAsync(entity, cancellationToken);
|
||||
await Context.SaveChangesAsync(cancellationToken);
|
||||
return entity;
|
||||
}
|
||||
|
||||
// --- READ ---
|
||||
|
||||
public async Task<TEntity?> GetByIdAsync(int id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _dbSet.FindAsync([id], cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TEntity>> GetAllAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _dbSet.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<TEntity>> FindAsync(
|
||||
Expression<Func<TEntity, bool>> predicate,
|
||||
int? skip = null,
|
||||
int? take = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var query = _dbSet.Where(predicate);
|
||||
|
||||
if (skip.HasValue)
|
||||
query = query.Skip(skip.Value);
|
||||
|
||||
if (take.HasValue)
|
||||
query = query.Take(take.Value);
|
||||
|
||||
return await query.ToListAsync(cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<TEntity?> FindFirstAsync(
|
||||
Expression<Func<TEntity, bool>> predicate,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _dbSet.FirstOrDefaultAsync(predicate, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<TEntity?> FindSingleAsync(
|
||||
Expression<Func<TEntity, bool>> predicate,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _dbSet.SingleOrDefaultAsync(predicate, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<int> CountAsync(
|
||||
Expression<Func<TEntity, bool>>? predicate = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return predicate == null
|
||||
? await _dbSet.CountAsync(cancellationToken)
|
||||
: await _dbSet.CountAsync(predicate, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<bool> AnyAsync(
|
||||
Expression<Func<TEntity, bool>> predicate,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return await _dbSet.AnyAsync(predicate, cancellationToken);
|
||||
}
|
||||
|
||||
// --- UPDATE ---
|
||||
|
||||
/// <summary>
|
||||
/// Updates a SINGLE entity that matches the predicate.
|
||||
/// Throws NotFoundException if 0 or 2+ records match.
|
||||
/// Auto-saves changes.
|
||||
/// </summary>
|
||||
public async Task UpdateSingleAsync<TDto>(
|
||||
Expression<Func<TEntity, bool>> predicate,
|
||||
TDto dto,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = await _dbSet.SingleOrDefaultAsync(predicate, cancellationToken)
|
||||
?? throw new NotFoundException($"No {typeof(TEntity).Name} found matching the predicate.");
|
||||
Mapper.Map(dto, entity);
|
||||
await Context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates ALL entities that match the predicate (bulk operation).
|
||||
/// Returns count of updated records.
|
||||
/// Auto-saves changes.
|
||||
/// </summary>
|
||||
public async Task<int> UpdateAsync<TDto>(
|
||||
Expression<Func<TEntity, bool>> predicate,
|
||||
TDto dto,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entities = await _dbSet.Where(predicate).ToListAsync(cancellationToken);
|
||||
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
Mapper.Map(dto, entity);
|
||||
}
|
||||
|
||||
await Context.SaveChangesAsync(cancellationToken);
|
||||
return entities.Count;
|
||||
}
|
||||
|
||||
// --- DELETE ---
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a SINGLE entity that matches the predicate.
|
||||
/// Throws NotFoundException if 0 or 2+ records match.
|
||||
/// Auto-saves changes.
|
||||
/// </summary>
|
||||
public async Task DeleteSingleAsync(
|
||||
Expression<Func<TEntity, bool>> predicate,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entity = await _dbSet.SingleOrDefaultAsync(predicate, cancellationToken)
|
||||
?? throw new NotFoundException($"No {typeof(TEntity).Name} found matching the predicate.");
|
||||
_dbSet.Remove(entity);
|
||||
await Context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes ALL entities that match the predicate (bulk operation).
|
||||
/// Returns count of deleted records.
|
||||
/// Auto-saves changes.
|
||||
/// </summary>
|
||||
public async Task<int> DeleteAsync(
|
||||
Expression<Func<TEntity, bool>> predicate,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var entities = await _dbSet.Where(predicate).ToListAsync(cancellationToken);
|
||||
|
||||
_dbSet.RemoveRange(entities);
|
||||
await Context.SaveChangesAsync(cancellationToken);
|
||||
return entities.Count;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user