diff --git a/DbFirst.Application/Catalogs/CatalogService.cs b/DbFirst.Application/Catalogs/CatalogService.cs index 1e2f5ce..d4488c2 100644 --- a/DbFirst.Application/Catalogs/CatalogService.cs +++ b/DbFirst.Application/Catalogs/CatalogService.cs @@ -32,8 +32,8 @@ public class CatalogService : ICatalogService var domainItem = _mapper.Map(dto); domainItem.AddedWho = "system"; domainItem.AddedWhen = DateTime.UtcNow; - domainItem.ChangedWho = null; - domainItem.ChangedWhen = null; + domainItem.ChangedWho = "system"; + domainItem.ChangedWhen = DateTime.UtcNow; var created = await _repository.AddAsync(domainItem, cancellationToken); return _mapper.Map(created); diff --git a/DbFirst.Infrastructure/ApplicationDbContext.cs b/DbFirst.Infrastructure/ApplicationDbContext.cs index 3f7ecea..7065533 100644 --- a/DbFirst.Infrastructure/ApplicationDbContext.cs +++ b/DbFirst.Infrastructure/ApplicationDbContext.cs @@ -10,49 +10,13 @@ public partial class ApplicationDbContext : DbContext { } - public virtual DbSet TbmyCatalogs { get; set; } public virtual DbSet VwmyCatalogs { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity(entity => - { - entity.HasKey(e => e.Guid); - - entity.ToTable("TBMY_CATALOG"); - - entity.HasIndex(e => e.CatTitle, "UQ_TBMY_CATALOG_TITLE").IsUnique(); - - entity.Property(e => e.Guid).HasColumnName("GUID"); - entity.Property(e => e.AddedWhen) - .HasDefaultValueSql("(getdate())") - .HasColumnType("datetime") - .HasColumnName("ADDED_WHEN"); - entity.Property(e => e.AddedWho) - .HasMaxLength(30) - .IsUnicode(false) - .HasDefaultValue("SYSTEM") - .HasColumnName("ADDED_WHO"); - entity.Property(e => e.CatString) - .HasMaxLength(900) - .IsUnicode(false) - .HasColumnName("CAT_STRING"); - entity.Property(e => e.CatTitle) - .HasMaxLength(100) - .IsUnicode(false) - .HasColumnName("CAT_TITLE"); - entity.Property(e => e.ChangedWhen) - .HasColumnType("datetime") - .HasColumnName("CHANGED_WHEN"); - entity.Property(e => e.ChangedWho) - .HasMaxLength(30) - .IsUnicode(false) - .HasColumnName("CHANGED_WHO"); - }); - modelBuilder.Entity(entity => { - entity.HasNoKey(); + entity.HasKey(e => e.Guid); entity.ToView("VWMY_CATALOG"); diff --git a/DbFirst.Infrastructure/Mappings/CatalogInfrastructureProfile.cs b/DbFirst.Infrastructure/Mappings/CatalogInfrastructureProfile.cs index e8e2c01..887e621 100644 --- a/DbFirst.Infrastructure/Mappings/CatalogInfrastructureProfile.cs +++ b/DbFirst.Infrastructure/Mappings/CatalogInfrastructureProfile.cs @@ -8,7 +8,6 @@ public class CatalogInfrastructureProfile : Profile { public CatalogInfrastructureProfile() { - CreateMap().ReverseMap(); CreateMap(); } } diff --git a/DbFirst.Infrastructure/Repositories/CatalogRepository.cs b/DbFirst.Infrastructure/Repositories/CatalogRepository.cs index db74c3e..293d2b2 100644 --- a/DbFirst.Infrastructure/Repositories/CatalogRepository.cs +++ b/DbFirst.Infrastructure/Repositories/CatalogRepository.cs @@ -33,24 +33,26 @@ public class CatalogRepository : ICatalogRepository public async Task AddAsync(Catalog catalog, CancellationToken cancellationToken = default) { - var entity = _mapper.Map(catalog); - _db.TbmyCatalogs.Add(entity); - await _db.SaveChangesAsync(cancellationToken); - return _mapper.Map(entity); + var created = await UpsertWithStoredProcedureAsync(catalog, cancellationToken); + if (created == null) + { + throw new InvalidOperationException("Failed to create catalog via stored procedure."); + } + + return created; } public async Task UpdateAsync(int id, Catalog catalog, CancellationToken cancellationToken = default) { - var entity = await _db.TbmyCatalogs.FirstOrDefaultAsync(x => x.Guid == id, cancellationToken); - if (entity == null) + var existing = await _db.VwmyCatalogs.AsNoTracking().AnyAsync(x => x.Guid == id, cancellationToken); + if (!existing) { return false; } - _mapper.Map(catalog, entity); - entity.Guid = id; - await _db.SaveChangesAsync(cancellationToken); - return true; + catalog.Guid = id; + var updated = await UpsertWithStoredProcedureAsync(catalog, cancellationToken); + return updated != null; } public async Task UpdateWithStoredProcedureAsync(Catalog catalog, CancellationToken cancellationToken = default) @@ -60,48 +62,18 @@ public class CatalogRepository : ICatalogRepository return null; } - var existing = await _db.TbmyCatalogs.AsNoTracking().FirstOrDefaultAsync(x => x.Guid == catalog.Guid, cancellationToken); - if (existing == null) + var existing = await _db.VwmyCatalogs.AsNoTracking().AnyAsync(x => x.Guid == catalog.Guid, cancellationToken); + if (!existing) { return null; } - var catTitleParam = new SqlParameter("@CAT_TITLE", existing.CatTitle); - var catStringParam = new SqlParameter("@CAT_STRING", catalog.CatString); - var changedWhoParam = new SqlParameter("@CHANGED_WHO", (object?)catalog.ChangedWho ?? DBNull.Value); - var guidOutParam = new SqlParameter("@GUID", SqlDbType.Int) { Direction = ParameterDirection.Output }; - - await _db.Database.ExecuteSqlRawAsync( - "EXEC dbo.PRTBMY_CATALOG_UPDATE @CAT_TITLE, @CAT_STRING, @CHANGED_WHO, @GUID OUTPUT", - parameters: new[] { catTitleParam, catStringParam, changedWhoParam, guidOutParam }, - cancellationToken: cancellationToken); - - if (guidOutParam.Value == DBNull.Value) - { - return null; - } - - var guid = (int)guidOutParam.Value; - var entity = await _db.TbmyCatalogs.AsNoTracking().FirstOrDefaultAsync(x => x.Guid == guid, cancellationToken); - return entity == null ? new Catalog { Guid = guid, CatTitle = existing.CatTitle, CatString = catalog.CatString, ChangedWho = catalog.ChangedWho } : _mapper.Map(entity); + return await UpsertWithStoredProcedureAsync(catalog, cancellationToken); } public async Task DeleteAsync(int id, CancellationToken cancellationToken = default) { - var entity = await _db.TbmyCatalogs.FirstOrDefaultAsync(x => x.Guid == id, cancellationToken); - if (entity == null) - { - return false; - } - - _db.TbmyCatalogs.Remove(entity); - await _db.SaveChangesAsync(cancellationToken); - return true; - } - - public async Task DeleteWithStoredProcedureAsync(int id, CancellationToken cancellationToken = default) - { - var exists = await _db.TbmyCatalogs.AsNoTracking().AnyAsync(x => x.Guid == id, cancellationToken); + var exists = await _db.VwmyCatalogs.AsNoTracking().AnyAsync(x => x.Guid == id, cancellationToken); if (!exists) { return false; @@ -115,4 +87,36 @@ public class CatalogRepository : ICatalogRepository return true; } + + public async Task DeleteWithStoredProcedureAsync(int id, CancellationToken cancellationToken = default) + { + return await DeleteAsync(id, cancellationToken); + } + + private async Task UpsertWithStoredProcedureAsync(Catalog catalog, CancellationToken cancellationToken) + { + var guidParam = new SqlParameter("@GUID", SqlDbType.Int) + { + Direction = ParameterDirection.InputOutput, + Value = catalog.Guid == 0 ? DBNull.Value : catalog.Guid + }; + + 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); + + await _db.Database.ExecuteSqlRawAsync( + "EXEC dbo.PRTBMY_CATALOG_UPDATE @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; + var viewRow = await _db.VwmyCatalogs.AsNoTracking().FirstOrDefaultAsync(x => x.Guid == guid, cancellationToken); + return viewRow == null ? null : _mapper.Map(viewRow); + } } diff --git a/DbFirst.Infrastructure/ScaffoldEntities/TbmyCatalog.cs b/DbFirst.Infrastructure/ScaffoldEntities/TbmyCatalog.cs deleted file mode 100644 index 625f208..0000000 --- a/DbFirst.Infrastructure/ScaffoldEntities/TbmyCatalog.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace DbFirst.Infrastructure.ScaffoldEntities; - -public partial class TbmyCatalog -{ - public int Guid { get; set; } - - public string CatTitle { get; set; } = null!; - - public string CatString { get; set; } = null!; - - public string AddedWho { get; set; } = null!; - - public DateTime AddedWhen { get; set; } - - public string? ChangedWho { get; set; } - - public DateTime? ChangedWhen { get; set; } - - // = null!; ist nur eine Null-Unterdrückung für Non‑Nullable-Referenztypen. Hintergrund: Die Spalten CatTitle, CatString, AddedWho - // sind in der DB als NOT NULL definiert, also generiert der Scaffold string (ohne ?). Damit der Compiler bei aktivierter Nullable-Analyse - // nicht warnt („non-nullable property is uninitialized“), wird ein Dummy-Init auf null! gesetzt. Das ! sagt dem Compiler „ich garantiere, - // dass zur Laufzeit ein Wert gesetzt wird“. Bei string? ChangedWho/DateTime? ChangedWhen sind die Spalten nullable, daher kein null! nötig. - // Bei Value Types wie int/DateTime braucht es ebenfalls kein Init, da sie Standardwerte haben. -}