Refactored IRepository<T> and ICatalogRepository to reside in the DbFirst.Application layer instead of Domain. Updated namespaces, using statements, and all references in services and handlers. Adjusted csproj dependencies to reflect the new structure. Updated comments to clarify Clean Architecture rationale and improved separation of concerns.
132 lines
5.2 KiB
C#
132 lines
5.2 KiB
C#
using DbFirst.Domain;
|
||
using DbFirst.Domain.Entities;
|
||
using DbFirst.Application.Repositories;
|
||
using Microsoft.Data.SqlClient;
|
||
using Microsoft.EntityFrameworkCore;
|
||
using System.Data;
|
||
|
||
namespace DbFirst.Infrastructure.Repositories;
|
||
|
||
// TODO: instead of creating implementation of repository per entity, consider using generic repository pattern (eg. Repository<T>) to reduce code duplication.
|
||
|
||
/* Copilot's Response:
|
||
|
||
A generic Repository<T> isn’t really worthwhile here:
|
||
• Reads from the view are generic, but inserts/updates/deletes go through stored procedures with special parameters/output GUIDs.You’d need lots of exceptions/overrides—little gain.
|
||
• Operations aren’t symmetric (separate procs for insert/update/delete with output handling and reload), so a one-size-fits-all CRUD pattern doesn’t fit well.
|
||
• Better to keep the specialized repo.If you want reuse, extract small helpers (e.g., for proc calls/output parameters/reload) instead of forcing a generic repository. */
|
||
|
||
public class CatalogRepository : ICatalogRepository
|
||
{
|
||
private readonly ApplicationDbContext _db;
|
||
|
||
public CatalogRepository(ApplicationDbContext db)
|
||
{
|
||
_db = db;
|
||
}
|
||
|
||
public async Task<List<VwmyCatalog>> GetAllAsync(CancellationToken cancellationToken = default)
|
||
{
|
||
return await _db.VwmyCatalogs.AsNoTracking().ToListAsync(cancellationToken);
|
||
}
|
||
|
||
public async Task<VwmyCatalog?> GetByIdAsync(int id, CancellationToken cancellationToken = default)
|
||
{
|
||
return await _db.VwmyCatalogs.AsNoTracking().FirstOrDefaultAsync(x => x.Guid == id, cancellationToken);
|
||
}
|
||
|
||
public async Task<VwmyCatalog?> GetByTitleAsync(string title, CancellationToken cancellationToken = default)
|
||
{
|
||
return await _db.VwmyCatalogs.AsNoTracking().FirstOrDefaultAsync(x => x.CatTitle == title, cancellationToken);
|
||
}
|
||
|
||
public async Task<VwmyCatalog> InsertAsync(VwmyCatalog catalog, CancellationToken cancellationToken = default)
|
||
{
|
||
var guidParam = new SqlParameter("@GUID", SqlDbType.Int)
|
||
{
|
||
Direction = ParameterDirection.Output
|
||
};
|
||
|
||
var catTitleParam = new SqlParameter("@CAT_TITLE", catalog.CatTitle);
|
||
var catStringParam = new SqlParameter("@CAT_STRING", catalog.CatString);
|
||
var addedWhoParam = new SqlParameter("@ADDED_WHO", (object?)catalog.AddedWho ?? DBNull.Value);
|
||
|
||
await _db.Database.ExecuteSqlRawAsync(
|
||
"EXEC dbo.PRTBMY_CATALOG_INSERT @CAT_TITLE, @CAT_STRING, @ADDED_WHO, @GUID OUTPUT",
|
||
parameters: new[] { catTitleParam, catStringParam, addedWhoParam, guidParam },
|
||
cancellationToken: cancellationToken);
|
||
|
||
if (guidParam.Value == DBNull.Value)
|
||
{
|
||
throw new InvalidOperationException("Failed to insert catalog via stored procedure.");
|
||
}
|
||
|
||
var guid = (int)guidParam.Value;
|
||
var created = await _db.VwmyCatalogs.AsNoTracking().FirstOrDefaultAsync(x => x.Guid == guid, cancellationToken);
|
||
if (created == null)
|
||
{
|
||
throw new InvalidOperationException("Inserted catalog could not be loaded from view.");
|
||
}
|
||
|
||
return created;
|
||
}
|
||
|
||
public async Task<VwmyCatalog?> UpdateAsync(int id, VwmyCatalog catalog, CatalogUpdateProcedure procedure, CancellationToken cancellationToken = default)
|
||
{
|
||
catalog.Guid = id;
|
||
|
||
var guidParam = new SqlParameter("@GUID", SqlDbType.Int)
|
||
{
|
||
Direction = ParameterDirection.Output
|
||
};
|
||
|
||
var catTitleParam = new SqlParameter("@CAT_TITLE", catalog.CatTitle);
|
||
var catStringParam = new SqlParameter("@CAT_STRING", catalog.CatString);
|
||
var changedWhoParam = new SqlParameter("@CHANGED_WHO", (object?)catalog.ChangedWho ?? DBNull.Value);
|
||
|
||
var procName = procedure == CatalogUpdateProcedure.Save
|
||
? "PRTBMY_CATALOG_SAVE"
|
||
: "PRTBMY_CATALOG_UPDATE";
|
||
|
||
await _db.Database.ExecuteSqlRawAsync(
|
||
$"EXEC dbo.{procName} @CAT_TITLE, @CAT_STRING, @CHANGED_WHO, @GUID OUTPUT",
|
||
parameters: new[] { catTitleParam, catStringParam, changedWhoParam, guidParam },
|
||
cancellationToken: cancellationToken);
|
||
|
||
if (guidParam.Value == DBNull.Value)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
var guid = (int)guidParam.Value;
|
||
if (guid == 0)
|
||
{
|
||
return null;
|
||
}
|
||
|
||
return await _db.VwmyCatalogs.AsNoTracking().FirstOrDefaultAsync(x => x.Guid == guid, cancellationToken);
|
||
}
|
||
|
||
public async Task<VwmyCatalog?> UpdateAsync(int id, VwmyCatalog catalog, CancellationToken cancellationToken = default)
|
||
{
|
||
return await UpdateAsync(id, catalog, CatalogUpdateProcedure.Update, cancellationToken);
|
||
}
|
||
|
||
public async Task<bool> DeleteAsync(int id, CancellationToken cancellationToken = default)
|
||
{
|
||
var exists = await _db.VwmyCatalogs.AsNoTracking().AnyAsync(x => x.Guid == id, cancellationToken);
|
||
if (!exists)
|
||
{
|
||
return false;
|
||
}
|
||
|
||
var guidParam = new SqlParameter("@GUID", id);
|
||
await _db.Database.ExecuteSqlRawAsync(
|
||
"EXEC dbo.PRTBMY_CATALOG_DELETE @GUID",
|
||
parameters: new[] { guidParam },
|
||
cancellationToken: cancellationToken);
|
||
|
||
return true;
|
||
}
|
||
}
|