Compare commits
18 Commits
main
...
b29ecb77df
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b29ecb77df | ||
|
|
063e8418f8 | ||
|
|
7a0e56e27a | ||
|
|
b86c006f25 | ||
|
|
efe186320d | ||
|
|
dbf46fffac | ||
|
|
f72c1bda2b | ||
|
|
eebfcdf3c7 | ||
|
|
35efac0d6c | ||
|
|
c336b772d4 | ||
|
|
55c75f84e4 | ||
|
|
6bef982fcc | ||
|
|
627c553e59 | ||
|
|
066a3f4389 | ||
|
|
6e5d08a8f4 | ||
|
|
dae7d1d979 | ||
|
|
4ef8047460 | ||
| b879095627 |
@@ -5,7 +5,7 @@ name: Branch - test - Build and Push Backend API Docker Image
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- test # Wird ausgelöst bei jedem Push auf den Master-Branch
|
- develop # Wird ausgelöst bei jedem Push auf den Master-Branch
|
||||||
|
|
||||||
# Definition der Jobs, die in diesem Workflow ausgeführt werden
|
# Definition der Jobs, die in diesem Workflow ausgeführt werden
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -77,15 +77,12 @@ namespace Webshop.Api.Controllers.Admin
|
|||||||
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)]
|
[ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status409Conflict)]
|
||||||
public async Task<IActionResult> UpdateAdminProduct(Guid id, [FromForm] UpdateAdminProductDto productDto)
|
public async Task<IActionResult> UpdateAdminProduct(Guid id, [FromForm] UpdateAdminProductDto productDto)
|
||||||
{
|
{
|
||||||
if (id != productDto.Id)
|
// ==============================================================================
|
||||||
{
|
// DEINE PERFEKTE L<>SUNG: URL-ID erzwingen
|
||||||
return BadRequest(new { Message = "ID in der URL und im Body stimmen nicht <20>berein." });
|
// ==============================================================================
|
||||||
}
|
productDto.Id = id;
|
||||||
if (!ModelState.IsValid)
|
|
||||||
{
|
|
||||||
return BadRequest(ModelState);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Jetzt den Service mit dem garantiert korrekten DTO aufrufen.
|
||||||
var result = await _adminProductService.UpdateAdminProductAsync(productDto);
|
var result = await _adminProductService.UpdateAdminProductAsync(productDto);
|
||||||
|
|
||||||
return result.Type switch
|
return result.Type switch
|
||||||
@@ -93,8 +90,7 @@ namespace Webshop.Api.Controllers.Admin
|
|||||||
ServiceResultType.Success => NoContent(),
|
ServiceResultType.Success => NoContent(),
|
||||||
ServiceResultType.NotFound => NotFound(new { Message = result.ErrorMessage }),
|
ServiceResultType.NotFound => NotFound(new { Message = result.ErrorMessage }),
|
||||||
ServiceResultType.Conflict => Conflict(new { Message = result.ErrorMessage }),
|
ServiceResultType.Conflict => Conflict(new { Message = result.ErrorMessage }),
|
||||||
ServiceResultType.InvalidInput => BadRequest(new { Message = result.ErrorMessage }),
|
_ => BadRequest(new { Message = result.ErrorMessage ?? "Ein Fehler ist aufgetreten." })
|
||||||
_ => StatusCode(StatusCodes.Status500InternalServerError, new { Message = result.ErrorMessage ?? "Ein unerwarteter Fehler ist aufgetreten." })
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,6 +163,8 @@ builder.Services.AddControllers()
|
|||||||
.AddJsonOptions(options =>
|
.AddJsonOptions(options =>
|
||||||
{
|
{
|
||||||
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
|
||||||
|
options.JsonSerializerOptions.DefaultIgnoreCondition =
|
||||||
|
System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull;
|
||||||
});
|
});
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
|
||||||
@@ -327,6 +329,6 @@ app.Run();
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//new git
|
//new image build
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -27,5 +27,6 @@ namespace Webshop.Application.DTOs.Products
|
|||||||
// << NEU >>
|
// << NEU >>
|
||||||
public bool IsFeatured { get; set; }
|
public bool IsFeatured { get; set; }
|
||||||
public int FeaturedDisplayOrder { get; set; }
|
public int FeaturedDisplayOrder { get; set; }
|
||||||
|
public byte[] RowVersion { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ namespace Webshop.Application.DTOs.Products
|
|||||||
public List<IFormFile>? AdditionalImageFiles { get; set; }
|
public List<IFormFile>? AdditionalImageFiles { get; set; }
|
||||||
public List<Guid>? ImagesToDelete { get; set; }
|
public List<Guid>? ImagesToDelete { get; set; }
|
||||||
|
|
||||||
public List<Guid> CategorieIds { get; set; } = new List<Guid>();
|
public List<Guid>? CategorieIds { get; set; } = new List<Guid>();
|
||||||
|
|
||||||
public decimal? Weight { get; set; }
|
public decimal? Weight { get; set; }
|
||||||
public decimal? OldPrice { get; set; }
|
public decimal? OldPrice { get; set; }
|
||||||
@@ -35,5 +35,7 @@ namespace Webshop.Application.DTOs.Products
|
|||||||
public decimal? PurchasePrice { get; set; }
|
public decimal? PurchasePrice { get; set; }
|
||||||
public bool IsFeatured { get; set; }
|
public bool IsFeatured { get; set; }
|
||||||
public int FeaturedDisplayOrder { get; set; }
|
public int FeaturedDisplayOrder { get; set; }
|
||||||
|
|
||||||
|
public string? RowVersion { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,8 @@ namespace Webshop.Application.Services.Admin
|
|||||||
IsFeatured = productDto.IsFeatured,
|
IsFeatured = productDto.IsFeatured,
|
||||||
FeaturedDisplayOrder = productDto.FeaturedDisplayOrder,
|
FeaturedDisplayOrder = productDto.FeaturedDisplayOrder,
|
||||||
Images = images,
|
Images = images,
|
||||||
Productcategories = productDto.CategorieIds.Select(cId => new Productcategorie { categorieId = cId }).ToList()
|
Productcategories = productDto.CategorieIds.Select(cId => new Productcategorie { categorieId = cId }).ToList(),
|
||||||
|
RowVersion = Guid.NewGuid().ToByteArray()
|
||||||
};
|
};
|
||||||
|
|
||||||
await _productRepository.AddProductAsync(newProduct);
|
await _productRepository.AddProductAsync(newProduct);
|
||||||
@@ -111,18 +112,133 @@ namespace Webshop.Application.Services.Admin
|
|||||||
#region Unchanged Methods
|
#region Unchanged Methods
|
||||||
public async Task<ServiceResult> UpdateAdminProductAsync(UpdateAdminProductDto productDto)
|
public async Task<ServiceResult> UpdateAdminProductAsync(UpdateAdminProductDto productDto)
|
||||||
{
|
{
|
||||||
var existingProduct = await _context.Products.Include(p => p.Images).Include(p => p.Productcategories).FirstOrDefaultAsync(p => p.Id == productDto.Id);
|
Console.WriteLine($"---- UPDATE START: Produkt-ID {productDto.Id} ----");
|
||||||
if (existingProduct == null) { return ServiceResult.Fail(ServiceResultType.NotFound, $"Produkt mit ID '{productDto.Id}' nicht gefunden."); }
|
// SCHRITT 1: Lade NUR das Hauptprodukt, ohne Relationen.
|
||||||
|
var existingProduct = await _context.Products.FirstOrDefaultAsync(p => p.Id == productDto.Id);
|
||||||
|
if (existingProduct == null)
|
||||||
|
{
|
||||||
|
return ServiceResult.Fail(ServiceResultType.NotFound, $"Produkt mit ID '{productDto.Id}' nicht gefunden.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- CONCURRENCY CHECK ---
|
||||||
|
if (!string.IsNullOrEmpty(productDto.RowVersion))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// <<<<<< WICHTIGE KORREKTUR HIER >>>>>>
|
||||||
|
// FormData wandelt "+" oft in " " um. Das reparieren wir hier:
|
||||||
|
string fixedRowVersion = productDto.RowVersion.Replace(" ", "+");
|
||||||
|
|
||||||
|
// 1. Umwandlung von String (Base64) zu Byte-Array
|
||||||
|
byte[] incomingRowVersion = Convert.FromBase64String(fixedRowVersion);
|
||||||
|
|
||||||
|
// DEBUG-LOGGING
|
||||||
|
string dbValue = Convert.ToBase64String(existingProduct.RowVersion ?? new byte[0]);
|
||||||
|
|
||||||
|
Console.WriteLine($"DB RowVersion: {dbValue}");
|
||||||
|
Console.WriteLine($"Frontend RowVersion: {fixedRowVersion}"); // Logge den reparierten Wert
|
||||||
|
|
||||||
|
if (dbValue != fixedRowVersion)
|
||||||
|
{
|
||||||
|
Console.WriteLine("!!! WARNUNG: Versionen stimmen nicht <20>berein !!!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Setze den Originalwert f<>r EF Core
|
||||||
|
_context.Entry(existingProduct).Property(p => p.RowVersion).OriginalValue = incomingRowVersion;
|
||||||
|
}
|
||||||
|
catch (FormatException)
|
||||||
|
{
|
||||||
|
return ServiceResult.Fail(ServiceResultType.Failure, "RowVersion Format ist ung<6E>ltig.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// SCHRITT 3: Lade jetzt die Relationen explizit nach.
|
||||||
|
await _context.Entry(existingProduct).Collection(p => p.Images).LoadAsync();
|
||||||
|
await _context.Entry(existingProduct).Collection(p => p.Productcategories).LoadAsync();
|
||||||
|
|
||||||
|
|
||||||
var skuExists = await _context.Products.AnyAsync(p => p.SKU == productDto.SKU && p.Id != productDto.Id);
|
var skuExists = await _context.Products.AnyAsync(p => p.SKU == productDto.SKU && p.Id != productDto.Id);
|
||||||
if (skuExists) { return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderes Produkt mit der SKU '{productDto.SKU}' existiert bereits."); }
|
if (skuExists) { return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderes Produkt mit der SKU '{productDto.SKU}' existiert bereits."); }
|
||||||
var slugExists = await _context.Products.AnyAsync(p => p.Slug == productDto.Slug && p.Id != productDto.Id);
|
var slugExists = await _context.Products.AnyAsync(p => p.Slug == productDto.Slug && p.Id != productDto.Id);
|
||||||
if (slugExists) { return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderes Produkt mit dem Slug '{productDto.Slug}' existiert bereits."); }
|
if (slugExists) { return ServiceResult.Fail(ServiceResultType.Conflict, $"Ein anderes Produkt mit dem Slug '{productDto.Slug}' existiert bereits."); }
|
||||||
if (productDto.ImagesToDelete != null && productDto.ImagesToDelete.Any()) { var imagesToRemove = existingProduct.Images.Where(img => productDto.ImagesToDelete.Contains(img.Id)).ToList(); _context.ProductImages.RemoveRange(imagesToRemove); }
|
|
||||||
if (productDto.MainImageFile != null) { var existingMainImage = existingProduct.Images.FirstOrDefault(img => img.IsMainImage); if (existingMainImage != null) _context.ProductImages.Remove(existingMainImage); await using var stream = productDto.MainImageFile.OpenReadStream(); var url = await _fileStorageService.SaveFileAsync(stream, productDto.MainImageFile.FileName, productDto.MainImageFile.ContentType); existingProduct.Images.Add(new ProductImage { Url = url, IsMainImage = true, DisplayOrder = 1 }); }
|
// --- BILDER-LOGGING ---
|
||||||
if (productDto.AdditionalImageFiles != null && productDto.AdditionalImageFiles.Any()) { int displayOrder = (existingProduct.Images.Any() ? existingProduct.Images.Max(i => i.DisplayOrder) : 0) + 1; foreach (var file in productDto.AdditionalImageFiles) { await using var stream = file.OpenReadStream(); var url = await _fileStorageService.SaveFileAsync(stream, file.FileName, file.ContentType); existingProduct.Images.Add(new ProductImage { Url = url, IsMainImage = false, DisplayOrder = displayOrder++ }); } }
|
if (productDto.ImagesToDelete != null && productDto.ImagesToDelete.Any())
|
||||||
existingProduct.Name = productDto.Name; existingProduct.Description = productDto.Description; existingProduct.SKU = productDto.SKU; existingProduct.Price = productDto.Price; existingProduct.IsActive = productDto.IsActive; existingProduct.StockQuantity = productDto.StockQuantity; existingProduct.Slug = productDto.Slug; existingProduct.Weight = productDto.Weight; existingProduct.OldPrice = productDto.OldPrice; existingProduct.SupplierId = productDto.SupplierId; existingProduct.PurchasePrice = productDto.PurchasePrice; existingProduct.LastModifiedDate = DateTimeOffset.UtcNow; existingProduct.IsFeatured = productDto.IsFeatured; existingProduct.FeaturedDisplayOrder = productDto.FeaturedDisplayOrder;
|
{
|
||||||
existingProduct.Productcategories.Clear(); if (productDto.CategorieIds != null) { foreach (var categorieId in productDto.CategorieIds) { existingProduct.Productcategories.Add(new Productcategorie { categorieId = categorieId }); } }
|
Console.WriteLine($"---- L<>SCHE {productDto.ImagesToDelete.Count} BILDER ----");
|
||||||
await _productRepository.UpdateProductAsync(existingProduct); return ServiceResult.Ok();
|
var imagesToRemove = existingProduct.Images.Where(img => productDto.ImagesToDelete.Contains(img.Id)).ToList();
|
||||||
|
_context.ProductImages.RemoveRange(imagesToRemove);
|
||||||
|
}
|
||||||
|
if (productDto.MainImageFile != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine("---- ERSETZE HAUPTBILD ----");
|
||||||
|
var existingMainImage = existingProduct.Images.FirstOrDefault(img => img.IsMainImage);
|
||||||
|
if (existingMainImage != null) _context.ProductImages.Remove(existingMainImage);
|
||||||
|
|
||||||
|
await using var stream = productDto.MainImageFile.OpenReadStream();
|
||||||
|
var url = await _fileStorageService.SaveFileAsync(stream, productDto.MainImageFile.FileName, productDto.MainImageFile.ContentType);
|
||||||
|
Console.WriteLine($"---- NEUE HAUPTBILD-URL: {url} ----");
|
||||||
|
existingProduct.Images.Add(new ProductImage { Url = url, IsMainImage = true, DisplayOrder = 1 });
|
||||||
|
}
|
||||||
|
if (productDto.AdditionalImageFiles != null && productDto.AdditionalImageFiles.Any())
|
||||||
|
{
|
||||||
|
Console.WriteLine($"---- F<>GE {productDto.AdditionalImageFiles.Count} NEUE BILDER HINZU ----");
|
||||||
|
int displayOrder = (existingProduct.Images.Any() ? existingProduct.Images.Max(i => i.DisplayOrder) : 0) + 1;
|
||||||
|
foreach (var file in productDto.AdditionalImageFiles)
|
||||||
|
{
|
||||||
|
await using var stream = file.OpenReadStream();
|
||||||
|
var url = await _fileStorageService.SaveFileAsync(stream, file.FileName, file.ContentType);
|
||||||
|
Console.WriteLine($"---- NEUE BILD-URL: {url} ----");
|
||||||
|
existingProduct.Images.Add(new ProductImage { Url = url, IsMainImage = false, DisplayOrder = displayOrder++ });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// --- EIGENSCHAFTEN-UPDATE ---
|
||||||
|
Console.WriteLine("---- AKTUALISIERE PRODUKT-EIGENSCHAFTEN ----");
|
||||||
|
existingProduct.Name = productDto.Name;
|
||||||
|
existingProduct.Description = productDto.Description;
|
||||||
|
existingProduct.SKU = productDto.SKU;
|
||||||
|
existingProduct.Price = productDto.Price;
|
||||||
|
existingProduct.IsActive = productDto.IsActive;
|
||||||
|
existingProduct.StockQuantity = productDto.StockQuantity;
|
||||||
|
existingProduct.Slug = productDto.Slug;
|
||||||
|
existingProduct.Weight = productDto.Weight;
|
||||||
|
existingProduct.OldPrice = productDto.OldPrice;
|
||||||
|
existingProduct.SupplierId = productDto.SupplierId;
|
||||||
|
existingProduct.PurchasePrice = productDto.PurchasePrice;
|
||||||
|
existingProduct.LastModifiedDate = DateTimeOffset.UtcNow;
|
||||||
|
existingProduct.IsFeatured = productDto.IsFeatured;
|
||||||
|
existingProduct.FeaturedDisplayOrder = productDto.FeaturedDisplayOrder;
|
||||||
|
existingProduct.RowVersion = Guid.NewGuid().ToByteArray();
|
||||||
|
|
||||||
|
// --- KATEGORIEN-UPDATE ---
|
||||||
|
Console.WriteLine("---- AKTUALISIERE KATEGORIEN ----");
|
||||||
|
existingProduct.Productcategories.Clear();
|
||||||
|
if (productDto.CategorieIds != null)
|
||||||
|
{
|
||||||
|
foreach (var categorieId in productDto.CategorieIds)
|
||||||
|
{
|
||||||
|
existingProduct.Productcategories.Add(new Productcategorie { categorieId = categorieId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCHRITT 5: Speichern (jetzt mit einem sauberen Change Tracker Zustand)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.WriteLine("---- RUFE SaveChangesAsync AUF ----");
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
Console.WriteLine("---- UPDATE BEENDET ----");
|
||||||
|
}
|
||||||
|
catch (DbUpdateConcurrencyException)
|
||||||
|
{
|
||||||
|
// Dieser Fehler tritt jetzt nur noch auf, wenn jemand anderes WIRKLICH
|
||||||
|
// die Daten in der Zwischenzeit ge<67>ndert hat.
|
||||||
|
return ServiceResult.Fail(ServiceResultType.Conflict, "Das Produkt wurde in der Zwischenzeit von jemand anderem bearbeitet. Bitte laden Sie die Seite neu.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ServiceResult.Ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ServiceResult> DeleteAdminProductAsync(Guid id)
|
public async Task<ServiceResult> DeleteAdminProductAsync(Guid id)
|
||||||
@@ -134,7 +250,7 @@ namespace Webshop.Application.Services.Admin
|
|||||||
|
|
||||||
private AdminProductDto MapToAdminDto(Product product)
|
private AdminProductDto MapToAdminDto(Product product)
|
||||||
{
|
{
|
||||||
return new AdminProductDto { Id = product.Id, Name = product.Name, Description = product.Description, SKU = product.SKU, Price = product.Price, OldPrice = product.OldPrice, IsActive = product.IsActive, IsInStock = product.IsInStock, StockQuantity = product.StockQuantity, Weight = product.Weight, Slug = product.Slug, CreatedDate = product.CreatedDate, LastModifiedDate = product.LastModifiedDate, SupplierId = product.SupplierId, PurchasePrice = product.PurchasePrice, IsFeatured = product.IsFeatured, FeaturedDisplayOrder = product.FeaturedDisplayOrder, categorieIds = product.Productcategories.Select(pc => pc.categorieId).ToList(), Images = product.Images.OrderBy(i => i.DisplayOrder).Select(img => new ProductImageDto { Id = img.Id, Url = img.Url, IsMainImage = img.IsMainImage, DisplayOrder = img.DisplayOrder }).ToList() };
|
return new AdminProductDto { Id = product.Id, Name = product.Name, Description = product.Description, SKU = product.SKU, Price = product.Price, OldPrice = product.OldPrice, IsActive = product.IsActive, IsInStock = product.IsInStock, StockQuantity = product.StockQuantity, Weight = product.Weight, Slug = product.Slug, CreatedDate = product.CreatedDate, LastModifiedDate = product.LastModifiedDate, SupplierId = product.SupplierId, PurchasePrice = product.PurchasePrice, IsFeatured = product.IsFeatured, FeaturedDisplayOrder = product.FeaturedDisplayOrder, categorieIds = product.Productcategories.Select(pc => pc.categorieId).ToList(), Images = product.Images.OrderBy(i => i.DisplayOrder).Select(img => new ProductImageDto { Id = img.Id, Url = img.Url, IsMainImage = img.IsMainImage, DisplayOrder = img.DisplayOrder }).ToList(), RowVersion = product.RowVersion };
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,5 +53,7 @@ namespace Webshop.Domain.Entities
|
|||||||
public virtual ICollection<ProductDiscount> ProductDiscounts { get; set; } = new List<ProductDiscount>();
|
public virtual ICollection<ProductDiscount> ProductDiscounts { get; set; } = new List<ProductDiscount>();
|
||||||
public virtual ICollection<Productcategorie> Productcategories { get; set; } = new List<Productcategorie>();
|
public virtual ICollection<Productcategorie> Productcategories { get; set; } = new List<Productcategorie>();
|
||||||
public virtual ICollection<ProductImage> Images { get; set; } = new List<ProductImage>();
|
public virtual ICollection<ProductImage> Images { get; set; } = new List<ProductImage>();
|
||||||
|
[ConcurrencyCheck]
|
||||||
|
public byte[] RowVersion { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ namespace Webshop.Domain.Interfaces
|
|||||||
Task<Product?> GetBySlugAsync(string slug);
|
Task<Product?> GetBySlugAsync(string slug);
|
||||||
Task AddProductAsync(Product product);
|
Task AddProductAsync(Product product);
|
||||||
Task UpdateProductAsync(Product product);
|
Task UpdateProductAsync(Product product);
|
||||||
|
Task SaveChangesAsync();
|
||||||
Task DeleteProductAsync(Guid id);
|
Task DeleteProductAsync(Guid id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
1367
Webshop.Infrastructure/Migrations/20251107143106_row.Designer.cs
generated
Normal file
1367
Webshop.Infrastructure/Migrations/20251107143106_row.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
Webshop.Infrastructure/Migrations/20251107143106_row.cs
Normal file
30
Webshop.Infrastructure/Migrations/20251107143106_row.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Webshop.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class row : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<byte[]>(
|
||||||
|
name: "RowVersion",
|
||||||
|
table: "Products",
|
||||||
|
type: "bytea",
|
||||||
|
rowVersion: true,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: new byte[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "RowVersion",
|
||||||
|
table: "Products");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1367
Webshop.Infrastructure/Migrations/20251120140457_rowversion.Designer.cs
generated
Normal file
1367
Webshop.Infrastructure/Migrations/20251120140457_rowversion.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Webshop.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class rowversion : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1366
Webshop.Infrastructure/Migrations/20251120141425_rowversion2.Designer.cs
generated
Normal file
1366
Webshop.Infrastructure/Migrations/20251120141425_rowversion2.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Webshop.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class rowversion2 : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1366
Webshop.Infrastructure/Migrations/20251120141924_rowversion3.Designer.cs
generated
Normal file
1366
Webshop.Infrastructure/Migrations/20251120141924_rowversion3.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Webshop.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class rowversion3 : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1366
Webshop.Infrastructure/Migrations/20251120143728_rowversion4.Designer.cs
generated
Normal file
1366
Webshop.Infrastructure/Migrations/20251120143728_rowversion4.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Webshop.Infrastructure.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class rowversion4 : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -613,6 +613,11 @@ namespace Webshop.Infrastructure.Migrations
|
|||||||
.HasPrecision(18, 2)
|
.HasPrecision(18, 2)
|
||||||
.HasColumnType("numeric(18,2)");
|
.HasColumnType("numeric(18,2)");
|
||||||
|
|
||||||
|
b.Property<byte[]>("RowVersion")
|
||||||
|
.IsConcurrencyToken()
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("bytea");
|
||||||
|
|
||||||
b.Property<string>("SKU")
|
b.Property<string>("SKU")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasMaxLength(50)
|
.HasMaxLength(50)
|
||||||
|
|||||||
@@ -55,5 +55,9 @@ namespace Webshop.Infrastructure.Repositories
|
|||||||
await _context.SaveChangesAsync();
|
await _context.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public async Task SaveChangesAsync()
|
||||||
|
{
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user