using Microsoft.EntityFrameworkCore;
using Strata.SqlTools.Breakdowns.SqlServer;
using Strata.SqlTools.EFCore.Abstractions;
using Strata.SqlTools.EFCore.Models;
namespace Strata.SqlTools.EFCore.Services;
///
/// Interface for a generic repository pattern for QueryBreakdown entities.
/// Provides a simplified API for common database operations.
///
public interface IQueryBreakdownRepository
{
///
/// Adds a new QueryBreakdown to the repository and saves changes.
///
/// The QueryBreakdown to add.
/// The ID of the added entity.
Task AddAsync(QueryBreakdown queryBreakdown);
///
/// Retrieves a QueryBreakdown by ID and converts it from the entity.
///
/// The ID of the QueryBreakdown entity.
/// The QueryBreakdown, or null if not found.
Task GetByIdAsync(int id);
///
/// Retrieves a QueryBreakdownEntity by ID.
///
/// The ID of the entity.
/// The QueryBreakdownEntity, or null if not found.
Task GetEntityByIdAsync(int id);
///
/// Gets all QueryBreakdowns.
///
/// A list of all QueryBreakdowns.
Task> GetAllAsync();
///
/// Gets all QueryBreakdownEntities.
///
/// A list of all QueryBreakdownEntities.
Task> GetAllEntitiesAsync();
///
/// Updates an existing QueryBreakdown and saves changes.
///
/// The ID of the entity to update.
/// The updated QueryBreakdown.
Task UpdateAsync(int id, QueryBreakdown queryBreakdown);
///
/// Deletes a QueryBreakdown by ID and saves changes.
///
/// The ID of the entity to delete.
/// True if the entity was deleted; false if not found.
Task DeleteAsync(int id);
///
/// Gets the count of all QueryBreakdown entities.
///
/// The count of entities.
Task GetCountAsync();
}
///
/// Implementation of IQueryBreakdownRepository for managing QueryBreakdown entities in Entity Framework Core.
///
public class QueryBreakdownRepository : IQueryBreakdownRepository
{
private readonly DbContext _context;
private readonly IQueryBreakdownMapper _mapper;
///
/// Initializes a new instance of the QueryBreakdownRepository.
///
/// The EF Core DbContext.
/// The mapper for converting between QueryBreakdown and QueryBreakdownEntity.
public QueryBreakdownRepository(DbContext context, IQueryBreakdownMapper mapper)
{
ArgumentNullException.ThrowIfNull(context);
ArgumentNullException.ThrowIfNull(mapper);
_context = context;
_mapper = mapper;
}
///
/// Adds a new QueryBreakdown to the repository and saves changes.
///
public async Task AddAsync(QueryBreakdown queryBreakdown)
{
ArgumentNullException.ThrowIfNull(queryBreakdown);
var (entity, parameters, withClauses) = _mapper.MapToEntityWithRelations(queryBreakdown);
// Add the main entity
_context.Set().Add(entity);
await _context.SaveChangesAsync();
// Add related entities with foreign key set
foreach (var param in parameters)
{
param.QueryBreakdownEntityId = entity.Id;
_context.Set().Add(param);
}
foreach (var withClause in withClauses)
{
withClause.QueryBreakdownEntityId = entity.Id;
_context.Set().Add(withClause);
}
await _context.SaveChangesAsync();
return entity.Id;
}
///
/// Retrieves a QueryBreakdown by ID and converts it from the entity.
///
public async Task GetByIdAsync(int id)
{
var entity = await _context.Set()
.Include(e => e.Parameters)
.Include(e => e.WithClauses)
.FirstOrDefaultAsync(e => e.Id == id);
return entity != null ? _mapper.MapToDomainModelWithRelations(entity) : null;
}
///
/// Retrieves a QueryBreakdownEntity by ID.
///
public async Task GetEntityByIdAsync(int id)
{
return await _context.Set()
.FirstOrDefaultAsync(e => e.Id == id);
}
///
/// Gets all QueryBreakdowns.
///
public async Task> GetAllAsync()
{
var entities = await _context.Set().ToListAsync();
return entities.ConvertAll(e => _mapper.MapToDomainModel(e));
}
///
/// Gets all QueryBreakdownEntities.
///
public async Task> GetAllEntitiesAsync()
{
return await _context.Set().ToListAsync();
}
///
/// Updates an existing QueryBreakdown and saves changes.
///
public async Task UpdateAsync(int id, QueryBreakdown queryBreakdown)
{
ArgumentNullException.ThrowIfNull(queryBreakdown);
var entity = await _context.Set().FirstOrDefaultAsync(e => e.Id == id);
if (entity == null)
{
throw new InvalidOperationException($"QueryBreakdown with ID {id} not found.");
}
var updatedEntity = _mapper.MapToEntity(queryBreakdown);
// Update the main entity
entity.SelectClause = updatedEntity.SelectClause;
entity.SelectClauseComment = updatedEntity.SelectClauseComment;
entity.FromClause = updatedEntity.FromClause;
entity.FromClauseComment = updatedEntity.FromClauseComment;
entity.WhereClause = updatedEntity.WhereClause;
entity.WhereClauseComment = updatedEntity.WhereClauseComment;
entity.GroupByClause = updatedEntity.GroupByClause;
entity.GroupByClauseComment = updatedEntity.GroupByClauseComment;
entity.HavingClause = updatedEntity.HavingClause;
entity.HavingClauseComment = updatedEntity.HavingClauseComment;
entity.OrderByClause = updatedEntity.OrderByClause;
entity.OrderByClauseComment = updatedEntity.OrderByClauseComment;
entity.WithClause = updatedEntity.WithClause;
entity.RawSql = updatedEntity.RawSql;
entity.SetupClausesJson = updatedEntity.SetupClausesJson;
entity.FinishClausesJson = updatedEntity.FinishClausesJson;
entity.ParametersJson = updatedEntity.ParametersJson;
entity.UpdatedAt = DateTime.UtcNow;
// Delete and recreate related entities
var existingParameters = _context.Set().Where(p => p.QueryBreakdownEntityId == id);
_context.Set().RemoveRange(existingParameters);
var existingWithClauses = _context.Set().Where(w => w.QueryBreakdownEntityId == id);
_context.Set().RemoveRange(existingWithClauses);
var (_, parameters, withClauses) = _mapper.MapToEntityWithRelations(queryBreakdown);
foreach (var param in parameters)
{
param.QueryBreakdownEntityId = id;
_context.Set().Add(param);
}
foreach (var withClause in withClauses)
{
withClause.QueryBreakdownEntityId = id;
_context.Set().Add(withClause);
}
await _context.SaveChangesAsync();
}
///
/// Deletes a QueryBreakdown by ID and saves changes.
///
public async Task DeleteAsync(int id)
{
var entity = await _context.Set().FirstOrDefaultAsync(e => e.Id == id);
if (entity == null)
{
return false;
}
_context.Set().Remove(entity);
await _context.SaveChangesAsync();
return true;
}
///
/// Gets the count of all QueryBreakdown entities.
///
public async Task GetCountAsync()
{
return await _context.Set().CountAsync();
}
}