diff --git a/ComputerShopBusinessLogic/BusinessLogics/AssemblyLogic.cs b/ComputerShopBusinessLogic/BusinessLogics/AssemblyLogic.cs new file mode 100644 index 0000000..43a1e7a --- /dev/null +++ b/ComputerShopBusinessLogic/BusinessLogics/AssemblyLogic.cs @@ -0,0 +1,117 @@ +using ComputerShopContracts.BindingModels; +using ComputerShopContracts.BusinessLogicContracts; +using ComputerShopContracts.SearchModels; +using ComputerShopContracts.StorageContracts; +using ComputerShopContracts.ViewModels; +using Microsoft.Extensions.Logging; + +namespace ComputerShopBusinessLogic.BusinessLogics +{ + public class AssemblyLogic : IAssemblyLogic + { + private readonly ILogger _logger; + private readonly IAssemblyStorage _assemblyStorage; + + public AssemblyLogic(ILogger Logger, IAssemblyStorage AssemblyStorage) + { + _logger = Logger; + _assemblyStorage = AssemblyStorage; + } + + public List? ReadList(AssemblySearchModel? Model) + { + var List = (Model == null) ? _assemblyStorage.GetFullList() : _assemblyStorage.GetFilteredList(Model); + + if (List == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + + _logger.LogInformation("ReadList. Count: {Count}", List.Count); + return List; + } + + public AssemblyViewModel? ReadElement(AssemblySearchModel Model) + { + if (Model == null) + throw new ArgumentNullException(nameof(Model)); + + var Element = _assemblyStorage.GetElement(Model); + if (Element == null) + { + _logger.LogWarning("ReadElement Assembly not found"); + return null; + } + + _logger.LogInformation("ReadElement Assembly found. Id: {Id}", Element.Id); + return Element; + } + + public bool Create(AssemblyBindingModel Model) + { + CheckModel(Model); + + if (_assemblyStorage.Insert(Model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + + return true; + } + + public bool Update(AssemblyBindingModel Model) + { + CheckModel(Model); + + if (_assemblyStorage.Update(Model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + + return true; + } + + public bool Delete(AssemblyBindingModel Model) + { + CheckModel(Model, false); + _logger.LogInformation("Delete. Id:{Id}", Model.Id); + + if (_assemblyStorage.Delete(Model) is null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + + return true; + } + + private void CheckModel(AssemblyBindingModel Model, bool WithParams = true) + { + if (Model == null) + throw new ArgumentNullException(nameof(Model)); + + if (!WithParams) + return; + + if (string.IsNullOrEmpty(Model.AssemblyName)) + throw new ArgumentException($"У сборки отсутствует название"); + + if (string.IsNullOrEmpty(Model.Category)) + throw new ArgumentException($"У сборки отсутствует категория"); + + if (Model.Price <= 0) + throw new ArgumentException("Цена сборки должна быть больше 0", nameof(Model.Price)); + + var Element = _assemblyStorage.GetElement(new AssemblySearchModel + { + AssemblyName = Model.AssemblyName + }); + + if (Element != null && Element.Id != Model.Id) + throw new InvalidOperationException("Товар с таким названием уже есть"); + } + } +} diff --git a/ComputerShopBusinessLogic/BusinessLogics/ComponentLogic.cs b/ComputerShopBusinessLogic/BusinessLogics/ComponentLogic.cs new file mode 100644 index 0000000..2f8fc59 --- /dev/null +++ b/ComputerShopBusinessLogic/BusinessLogics/ComponentLogic.cs @@ -0,0 +1,114 @@ +using ComputerShopContracts.BindingModels; +using ComputerShopContracts.BusinessLogicContracts; +using ComputerShopContracts.SearchModels; +using ComputerShopContracts.StorageContracts; +using ComputerShopContracts.ViewModels; +using Microsoft.Extensions.Logging; + +namespace ComputerShopBusinessLogic.BusinessLogics +{ + public class ComponentLogic : IComponentLogic + { + private readonly ILogger _logger; + private readonly IComponentStorage _componentStorage; + + public ComponentLogic(ILogger Logger, IComponentStorage ComponentStorage) + { + _logger = Logger; + _componentStorage = ComponentStorage; + } + + public List? ReadList(ComponentSearchModel? Model) + { + var List = (Model == null) ? _componentStorage.GetFullList() : _componentStorage.GetFilteredList(Model); + + if (List == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + + _logger.LogInformation("ReadList. Count: {Count}", List.Count); + return List; + } + + public ComponentViewModel? ReadElement(ComponentSearchModel Model) + { + if (Model == null) + throw new ArgumentNullException(nameof(Model)); + + var Element = _componentStorage.GetElement(Model); + if (Element == null) + { + _logger.LogWarning("ReadElement component not found"); + return null; + } + + _logger.LogInformation("ReadElement component found. Id: {Id}", Element.Id); + return Element; + } + + public bool Create(ComponentBindingModel Model) + { + CheckModel(Model); + + if (_componentStorage.Insert(Model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + + return true; + } + + public bool Update(ComponentBindingModel Model) + { + CheckModel(Model); + + if (_componentStorage.Update(Model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + + return true; + } + + public bool Delete(ComponentBindingModel Model) + { + CheckModel(Model, false); + _logger.LogInformation("Delete. Id:{Id}", Model.Id); + + if (_componentStorage.Delete(Model) is null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + + return true; + } + + private void CheckModel(ComponentBindingModel Model, bool WithParams = true) + { + if (Model == null) + throw new ArgumentNullException(nameof(Model)); + + if (!WithParams) + return; + + if (string.IsNullOrEmpty(Model.ComponentName)) + throw new ArgumentException($"У комплектующей отсутствует название"); + + if (Model.Cost <= 0) + throw new ArgumentException("Цена комплектующей должна быть больше 0", nameof(Model.Cost)); + + var Element = _componentStorage.GetElement(new ComponentSearchModel + { + ComponentName = Model.ComponentName + }); + + if (Element != null && Element.Id != Model.Id) + throw new InvalidOperationException("Комплектующая с таким названием уже есть"); + } + } +} diff --git a/ComputerShopBusinessLogic/BusinessLogics/ProductLogic.cs b/ComputerShopBusinessLogic/BusinessLogics/ProductLogic.cs new file mode 100644 index 0000000..8497091 --- /dev/null +++ b/ComputerShopBusinessLogic/BusinessLogics/ProductLogic.cs @@ -0,0 +1,117 @@ +using ComputerShopContracts.BindingModels; +using ComputerShopContracts.BusinessLogicContracts; +using ComputerShopContracts.SearchModels; +using ComputerShopContracts.StorageContracts; +using ComputerShopContracts.ViewModels; +using Microsoft.Extensions.Logging; + +namespace ComputerShopBusinessLogic.BusinessLogics +{ + public class ProductLogic : IProductLogic + { + private readonly ILogger _logger; + private readonly IProductStorage _productStorage; + + public ProductLogic(ILogger Logger, IProductStorage ProductStorage) + { + _logger = Logger; + _productStorage = ProductStorage; + } + + public List? ReadList(ProductSearchModel? Model) + { + var List = (Model == null) ? _productStorage.GetFullList() : _productStorage.GetFilteredList(Model); + + if (List == null) + { + _logger.LogWarning("ReadList return null list"); + return null; + } + + _logger.LogInformation("ReadList. Count: {Count}", List.Count); + return List; + } + + public ProductViewModel? ReadElement(ProductSearchModel Model) + { + if (Model == null) + throw new ArgumentNullException(nameof(Model)); + + var Element = _productStorage.GetElement(Model); + if (Element == null) + { + _logger.LogWarning("ReadElement Product not found"); + return null; + } + + _logger.LogInformation("ReadElement Product found. Id: {Id}", Element.Id); + return Element; + } + + public bool Create(ProductBindingModel Model) + { + CheckModel(Model); + + if (_productStorage.Insert(Model) == null) + { + _logger.LogWarning("Insert operation failed"); + return false; + } + + return true; + } + + public bool Update(ProductBindingModel Model) + { + CheckModel(Model); + + if (_productStorage.Update(Model) == null) + { + _logger.LogWarning("Update operation failed"); + return false; + } + + return true; + } + + public bool Delete(ProductBindingModel Model) + { + CheckModel(Model, false); + _logger.LogInformation("Delete. Id:{Id}", Model.Id); + + if (_productStorage.Delete(Model) is null) + { + _logger.LogWarning("Delete operation failed"); + return false; + } + + return true; + } + + private void CheckModel(ProductBindingModel Model, bool WithParams = true) + { + if (Model == null) + throw new ArgumentNullException(nameof(Model)); + + if (!WithParams) + return; + + if (string.IsNullOrEmpty(Model.ProductName)) + throw new ArgumentException($"У товара отсутствует название"); + + if (Model.Price <= 0) + throw new ArgumentException("Цена товара должна быть больше 0", nameof(Model.Price)); + + if (Model.Warranty <= 0) + throw new ArgumentException("Гарантия на товар должна быть больше 0", nameof(Model.Warranty)); + + var Element = _productStorage.GetElement(new ProductSearchModel + { + ProductName = Model.ProductName + }); + + if (Element != null && Element.Id != Model.Id) + throw new InvalidOperationException("Товар с таким названием уже есть"); + } + } +} diff --git a/ComputerShopContracts/BindingModels/AssemblyBindingModel.cs b/ComputerShopContracts/BindingModels/AssemblyBindingModel.cs index 956cc7d..6ca738d 100644 --- a/ComputerShopContracts/BindingModels/AssemblyBindingModel.cs +++ b/ComputerShopContracts/BindingModels/AssemblyBindingModel.cs @@ -10,7 +10,7 @@ namespace ComputerShopContracts.BindingModels public string AssemblyName { get; set; } = string.Empty; - public double Cost { get; set; } + public double Price { get; set; } public string Category { get; set; } = string.Empty; diff --git a/ComputerShopContracts/BindingModels/ProductBindingModel.cs b/ComputerShopContracts/BindingModels/ProductBindingModel.cs index 18856cd..9991cb2 100644 --- a/ComputerShopContracts/BindingModels/ProductBindingModel.cs +++ b/ComputerShopContracts/BindingModels/ProductBindingModel.cs @@ -7,15 +7,15 @@ namespace ComputerShopContracts.BindingModels public int Id { get; set; } public int UserId { get; set; } + + public int? ShipmentId { get; set; } public string ProductName { get; set; } = string.Empty; - public double Cost { get; set; } + public double Price { get; set; } public int Warranty { get; set; } public Dictionary ProductComponents { get; set; } = new(); - - public int? ShipmentId { get; set; } } } diff --git a/ComputerShopContracts/SearchModels/AssemblySearchModel.cs b/ComputerShopContracts/SearchModels/AssemblySearchModel.cs index c15871b..9fe6f40 100644 --- a/ComputerShopContracts/SearchModels/AssemblySearchModel.cs +++ b/ComputerShopContracts/SearchModels/AssemblySearchModel.cs @@ -6,6 +6,8 @@ public int? UserId { get; set; } + public string? AssemblyName { get; set; } + public string? Category { get; set; } } } diff --git a/ComputerShopContracts/SearchModels/ComponentSearchModel.cs b/ComputerShopContracts/SearchModels/ComponentSearchModel.cs index 3a4bb83..8ee445c 100644 --- a/ComputerShopContracts/SearchModels/ComponentSearchModel.cs +++ b/ComputerShopContracts/SearchModels/ComponentSearchModel.cs @@ -5,5 +5,7 @@ public int? Id { get; set; } public int? UserId { get; set; } + + public string? ComponentName { get; set; } } } diff --git a/ComputerShopContracts/SearchModels/ProductSearchModel.cs b/ComputerShopContracts/SearchModels/ProductSearchModel.cs index 60e81eb..4c7065a 100644 --- a/ComputerShopContracts/SearchModels/ProductSearchModel.cs +++ b/ComputerShopContracts/SearchModels/ProductSearchModel.cs @@ -7,5 +7,7 @@ public int? UserId { get; set; } public int? ShipmentId { get; set; } + + public string? ProductName { get; set; } } } diff --git a/ComputerShopContracts/ViewModels/AssemblyViewModel.cs b/ComputerShopContracts/ViewModels/AssemblyViewModel.cs index 27ef688..4a10b30 100644 --- a/ComputerShopContracts/ViewModels/AssemblyViewModel.cs +++ b/ComputerShopContracts/ViewModels/AssemblyViewModel.cs @@ -13,7 +13,7 @@ namespace ComputerShopContracts.ViewModels public string AssemblyName { get; set; } = string.Empty; [DisplayName("Стоимость")] - public double Cost { get; set; } + public double Price { get; set; } [DisplayName("Категория")] public string Category { get; set; } = string.Empty; diff --git a/ComputerShopContracts/ViewModels/ProductViewModel.cs b/ComputerShopContracts/ViewModels/ProductViewModel.cs index 88577f0..6853f23 100644 --- a/ComputerShopContracts/ViewModels/ProductViewModel.cs +++ b/ComputerShopContracts/ViewModels/ProductViewModel.cs @@ -9,20 +9,20 @@ namespace ComputerShopContracts.ViewModels public int UserId { get; set; } + public int? ShipmentId { get; set; } + + [DisplayName("Поставщик")] + public string? ProviderName { get; set; } + [DisplayName("Название товара")] public string ProductName { get; set; } = string.Empty; [DisplayName("Стоимость")] - public double Cost { get; set; } + public double Price { get; set; } [DisplayName("Гарантия (мес.)")] public int Warranty { get; set; } public Dictionary ProductComponents { get; set; } = new(); - - public int? ShipmentId { get; set; } - - [DisplayName("Поставщик")] - public string ProviderName { get; set; } = string.Empty; } } diff --git a/ComputerShopDataModels/Models/IAssemblyModel.cs b/ComputerShopDataModels/Models/IAssemblyModel.cs index fa6bdcb..3a0b933 100644 --- a/ComputerShopDataModels/Models/IAssemblyModel.cs +++ b/ComputerShopDataModels/Models/IAssemblyModel.cs @@ -18,7 +18,7 @@ /// /// Стоимость /// - double Cost { get; } + double Price { get; } /// /// Категория diff --git a/ComputerShopDataModels/Models/IProductModel.cs b/ComputerShopDataModels/Models/IProductModel.cs index 65fa951..d15baca 100644 --- a/ComputerShopDataModels/Models/IProductModel.cs +++ b/ComputerShopDataModels/Models/IProductModel.cs @@ -18,7 +18,7 @@ /// /// Стоимость товара /// - double Cost { get; } + double Price { get; } /// /// Гарантия diff --git a/ComputerShopDatabaseImplement/Implements/AssemblyStorage.cs b/ComputerShopDatabaseImplement/Implements/AssemblyStorage.cs new file mode 100644 index 0000000..4fd4cde --- /dev/null +++ b/ComputerShopDatabaseImplement/Implements/AssemblyStorage.cs @@ -0,0 +1,121 @@ +using ComputerShopContracts.BindingModels; +using ComputerShopContracts.SearchModels; +using ComputerShopContracts.StorageContracts; +using ComputerShopContracts.ViewModels; +using ComputerShopDatabaseImplement.Models; +using Microsoft.EntityFrameworkCore; + +namespace ComputerShopDatabaseImplement.Implements +{ + public class AssemblyStorage : IAssemblyStorage + { + public List GetFullList() + { + using var Context = new ComputerShopDatabase(); + + return Context.Assemblies + .Include(x => x.Components) + .ThenInclude(x => x.Assembly) + .Select(x => x.ViewModel) + .ToList(); + } + + public List GetFilteredList(AssemblySearchModel Model) + { + using var Context = new ComputerShopDatabase(); + + // Optional search by Category name + if (!string.IsNullOrEmpty(Model.Category)) + { + return Context.Assemblies + .Include(x => x.Components) + .ThenInclude(x => x.Assembly) + .Where(x => x.UserId == Model.UserId && x.Category == Model.Category) + .Select(x => x.ViewModel) + .ToList(); + } + + return Context.Assemblies + .Include(x => x.Components) + .ThenInclude(x => x.Assembly) + .Where(x => x.UserId == Model.UserId) + .Select(x => x.ViewModel) + .ToList(); + } + + public AssemblyViewModel? GetElement(AssemblySearchModel Model) + { + using var Context = new ComputerShopDatabase(); + + // AssemblyName is unique + if (!string.IsNullOrEmpty(Model.AssemblyName)) + { + return Context.Assemblies + .Include(x => x.Components) + .ThenInclude(x => x.Assembly) + .FirstOrDefault(x => x.AssemblyName == Model.AssemblyName)? + .ViewModel; + } + + return Context.Assemblies + .Include(x => x.Components) + .ThenInclude(x => x.Assembly) + .FirstOrDefault(x => x.Id == Model.Id)? + .ViewModel; + } + + public AssemblyViewModel? Insert(AssemblyBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + + var NewAssembly = Assembly.Create(Context, Model); + Context.Assemblies.Add(NewAssembly); + Context.SaveChanges(); + + return NewAssembly.ViewModel; + } + + public AssemblyViewModel? Update(AssemblyBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + using var Transaction = Context.Database.BeginTransaction(); + + try + { + var ExistingAssembly = Context.Assemblies.FirstOrDefault(x => x.Id == Model.Id); + if (ExistingAssembly == null) + { + return null; + } + + ExistingAssembly.Update(Model); + Context.SaveChanges(); + ExistingAssembly.UpdateComponents(Context, Model); + Transaction.Commit(); + + return ExistingAssembly.ViewModel; + } + catch + { + Transaction.Rollback(); + throw; + } + } + + public AssemblyViewModel? Delete(AssemblyBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + + var ExistingAssembly = Context.Assemblies.Include(x => x.Components).FirstOrDefault(x => x.Id == Model.Id); + if (ExistingAssembly == null) + { + return null; + } + + Context.Assemblies.Remove(ExistingAssembly); + Context.SaveChanges(); + + return ExistingAssembly.ViewModel; + } + } +} diff --git a/ComputerShopDatabaseImplement/Implements/ComponentStorage.cs b/ComputerShopDatabaseImplement/Implements/ComponentStorage.cs new file mode 100644 index 0000000..0b0a5c2 --- /dev/null +++ b/ComputerShopDatabaseImplement/Implements/ComponentStorage.cs @@ -0,0 +1,90 @@ +using ComputerShopContracts.BindingModels; +using ComputerShopContracts.SearchModels; +using ComputerShopContracts.StorageContracts; +using ComputerShopContracts.ViewModels; +using ComputerShopDatabaseImplement.Models; + +namespace ComputerShopDatabaseImplement.Implements +{ + public class ComponentStorage : IComponentStorage + { + public List GetFullList() + { + using var Context = new ComputerShopDatabase(); + + return Context.Components + .Select(x => x.ViewModel) + .ToList(); + } + + public List GetFilteredList(ComponentSearchModel Model) + { + using var Context = new ComputerShopDatabase(); + + return Context.Components + .Where(x => x.UserId == Model.UserId) + .Select(x => x.ViewModel) + .ToList(); + } + + public ComponentViewModel? GetElement(ComponentSearchModel Model) + { + using var Context = new ComputerShopDatabase(); + + // ComponentName is unique + if (!string.IsNullOrEmpty(Model.ComponentName)) + { + return Context.Components + .FirstOrDefault(x => x.ComponentName == Model.ComponentName)? + .ViewModel; + } + + return Context.Components + .FirstOrDefault(x => x.Id == Model.Id)? + .ViewModel; + } + + public ComponentViewModel? Insert(ComponentBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + + var NewComponent = Component.Create(Model); + Context.Components.Add(NewComponent); + Context.SaveChanges(); + + return NewComponent.ViewModel; + } + + public ComponentViewModel? Update(ComponentBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + + var ExistingComponent = Context.Components.FirstOrDefault(x => x.Id == Model.Id); + if (ExistingComponent == null) + { + return null; + } + + ExistingComponent.Update(Model); + Context.SaveChanges(); + + return ExistingComponent.ViewModel; + } + + public ComponentViewModel? Delete(ComponentBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + + var ExistingComponent = Context.Components.FirstOrDefault(x => x.Id == Model.Id); + if (ExistingComponent == null) + { + return null; + } + + Context.Components.Remove(ExistingComponent); + Context.SaveChanges(); + + return ExistingComponent.ViewModel; + } + } +} diff --git a/ComputerShopDatabaseImplement/Implements/ProductStorage.cs b/ComputerShopDatabaseImplement/Implements/ProductStorage.cs new file mode 100644 index 0000000..68c8a73 --- /dev/null +++ b/ComputerShopDatabaseImplement/Implements/ProductStorage.cs @@ -0,0 +1,126 @@ +using ComputerShopContracts.BindingModels; +using ComputerShopContracts.SearchModels; +using ComputerShopContracts.StorageContracts; +using ComputerShopContracts.ViewModels; +using ComputerShopDatabaseImplement.Models; +using Microsoft.EntityFrameworkCore; + +namespace ComputerShopDatabaseImplement.Implements +{ + public class ProductStorage : IProductStorage + { + public List GetFullList() + { + using var Context = new ComputerShopDatabase(); + + return Context.Products + .Include(x => x.Shipment) + .Include(x => x.Components) + .ThenInclude(x => x.Product) + .Select(x => x.ViewModel) + .ToList(); + } + + public List GetFilteredList(ProductSearchModel Model) + { + using var Context = new ComputerShopDatabase(); + + // Optional search by Shipment + if (Model.ShipmentId.HasValue) + { + return Context.Products + .Include(x => x.Shipment) + .Include(x => x.Components) + .ThenInclude(x => x.Product) + .Where(x => x.UserId == Model.UserId && x.ShipmentId == Model.ShipmentId) + .Select(x => x.ViewModel) + .ToList(); + } + + return Context.Products + .Include(x => x.Shipment) + .Include(x => x.Components) + .ThenInclude(x => x.Product) + .Where(x => x.UserId == Model.UserId) + .Select(x => x.ViewModel) + .ToList(); + } + + public ProductViewModel? GetElement(ProductSearchModel Model) + { + using var Context = new ComputerShopDatabase(); + + // ProductName is unique + if (!string.IsNullOrEmpty(Model.ProductName)) + { + return Context.Products + .Include(x => x.Shipment) + .Include(x => x.Components) + .ThenInclude(x => x.Product) + .FirstOrDefault(x => x.ProductName == Model.ProductName)? + .ViewModel; + } + + return Context.Products + .Include(x => x.Shipment) + .Include(x => x.Components) + .ThenInclude(x => x.Product) + .FirstOrDefault(x => x.Id == Model.Id)? + .ViewModel; + } + + public ProductViewModel? Insert(ProductBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + + var NewProduct = Product.Create(Context, Model); + Context.Products.Add(NewProduct); + Context.SaveChanges(); + + return NewProduct.ViewModel; + } + + public ProductViewModel? Update(ProductBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + using var Transaction = Context.Database.BeginTransaction(); + + try + { + var ExistingProduct = Context.Products.FirstOrDefault(x => x.Id == Model.Id); + if (ExistingProduct == null) + { + return null; + } + + ExistingProduct.Update(Model); + Context.SaveChanges(); + ExistingProduct.UpdateComponents(Context, Model); + Transaction.Commit(); + + return ExistingProduct.ViewModel; + } + catch + { + Transaction.Rollback(); + throw; + } + } + + public ProductViewModel? Delete(ProductBindingModel Model) + { + using var Context = new ComputerShopDatabase(); + + var ExistingProduct = Context.Products.Include(x => x.Components).FirstOrDefault(x => x.Id == Model.Id); + if (ExistingProduct == null) + { + return null; + } + + Context.Products.Remove(ExistingProduct); + Context.SaveChanges(); + + return ExistingProduct.ViewModel; + } + } +} diff --git a/ComputerShopDatabaseImplement/Migrations/20240501095656_Переименовал Price (Олег).Designer.cs b/ComputerShopDatabaseImplement/Migrations/20240501095656_Переименовал Price (Олег).Designer.cs new file mode 100644 index 0000000..e31d67e --- /dev/null +++ b/ComputerShopDatabaseImplement/Migrations/20240501095656_Переименовал Price (Олег).Designer.cs @@ -0,0 +1,522 @@ +// +using System; +using ComputerShopDatabaseImplement; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace ComputerShopDatabaseImplement.Migrations +{ + [DbContext(typeof(ComputerShopDatabase))] + [Migration("20240501095656_Переименовал Price (Олег)")] + partial class ПереименовалPriceОлег + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.18") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Assembly", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssemblyName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Category") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("double precision"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Assemblies"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.AssemblyComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssemblyId") + .HasColumnType("integer"); + + b.Property("ComponentId") + .HasColumnType("integer"); + + b.Property("Count") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("AssemblyId"); + + b.HasIndex("ComponentId"); + + b.ToTable("AssemblyComponents"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Component", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ComponentName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Cost") + .HasColumnType("double precision"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Components"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateCreate") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("Sum") + .HasColumnType("double precision"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Price") + .HasColumnType("double precision"); + + b.Property("ProductName") + .IsRequired() + .HasColumnType("text"); + + b.Property("ShipmentId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.Property("Warranty") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ShipmentId"); + + b.HasIndex("UserId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ProductComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ComponentId") + .HasColumnType("integer"); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("ProductId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ComponentId"); + + b.HasIndex("ProductId"); + + b.ToTable("ProductComponents"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Request", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AssemblyId") + .HasColumnType("integer"); + + b.Property("ClientFIO") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateRequest") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("AssemblyId"); + + b.HasIndex("UserId"); + + b.ToTable("Requests"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.RequestOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OrderId") + .HasColumnType("integer"); + + b.Property("RequestId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("RequestId"); + + b.ToTable("RequestOrders"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Shipment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateShipment") + .HasColumnType("timestamp without time zone"); + + b.Property("ProviderName") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("Shipments"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ShipmentOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("OrderId") + .HasColumnType("integer"); + + b.Property("ShipmentId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("OrderId"); + + b.HasIndex("ShipmentId"); + + b.ToTable("ShipmentOrders"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Email") + .IsRequired() + .HasColumnType("text"); + + b.Property("Login") + .IsRequired() + .HasColumnType("text"); + + b.Property("Password") + .IsRequired() + .HasColumnType("text"); + + b.Property("Role") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Assembly", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.User", null) + .WithMany("Assemblies") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.AssemblyComponent", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.Assembly", "Assembly") + .WithMany("Components") + .HasForeignKey("AssemblyId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ComputerShopDatabaseImplement.Models.Component", "Component") + .WithMany("AssemblyComponents") + .HasForeignKey("ComponentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assembly"); + + b.Navigation("Component"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Component", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.User", null) + .WithMany("Components") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Order", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.User", null) + .WithMany("Orders") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Product", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.Shipment", "Shipment") + .WithMany("Products") + .HasForeignKey("ShipmentId"); + + b.HasOne("ComputerShopDatabaseImplement.Models.User", null) + .WithMany("Proucts") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Shipment"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ProductComponent", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.Component", "Component") + .WithMany("ProductComponents") + .HasForeignKey("ComponentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ComputerShopDatabaseImplement.Models.Product", "Product") + .WithMany("Components") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Component"); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Request", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.Assembly", "Assembly") + .WithMany("Requests") + .HasForeignKey("AssemblyId"); + + b.HasOne("ComputerShopDatabaseImplement.Models.User", "User") + .WithMany("Requests") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Assembly"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.RequestOrder", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.Order", "Order") + .WithMany("Requests") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ComputerShopDatabaseImplement.Models.Request", "Request") + .WithMany("Orders") + .HasForeignKey("RequestId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Order"); + + b.Navigation("Request"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Shipment", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.User", null) + .WithMany("Shipments") + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.ShipmentOrder", b => + { + b.HasOne("ComputerShopDatabaseImplement.Models.Order", "Order") + .WithMany("Shipments") + .HasForeignKey("OrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ComputerShopDatabaseImplement.Models.Shipment", "Shipment") + .WithMany("Orders") + .HasForeignKey("ShipmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Order"); + + b.Navigation("Shipment"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Assembly", b => + { + b.Navigation("Components"); + + b.Navigation("Requests"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Component", b => + { + b.Navigation("AssemblyComponents"); + + b.Navigation("ProductComponents"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Order", b => + { + b.Navigation("Requests"); + + b.Navigation("Shipments"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Product", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Request", b => + { + b.Navigation("Orders"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.Shipment", b => + { + b.Navigation("Orders"); + + b.Navigation("Products"); + }); + + modelBuilder.Entity("ComputerShopDatabaseImplement.Models.User", b => + { + b.Navigation("Assemblies"); + + b.Navigation("Components"); + + b.Navigation("Orders"); + + b.Navigation("Proucts"); + + b.Navigation("Requests"); + + b.Navigation("Shipments"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ComputerShopDatabaseImplement/Migrations/20240501095656_Переименовал Price (Олег).cs b/ComputerShopDatabaseImplement/Migrations/20240501095656_Переименовал Price (Олег).cs new file mode 100644 index 0000000..5564cea --- /dev/null +++ b/ComputerShopDatabaseImplement/Migrations/20240501095656_Переименовал Price (Олег).cs @@ -0,0 +1,38 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ComputerShopDatabaseImplement.Migrations +{ + /// + public partial class ПереименовалPriceОлег : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Cost", + table: "Products", + newName: "Price"); + + migrationBuilder.RenameColumn( + name: "Cost", + table: "Assemblies", + newName: "Price"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.RenameColumn( + name: "Price", + table: "Products", + newName: "Cost"); + + migrationBuilder.RenameColumn( + name: "Price", + table: "Assemblies", + newName: "Cost"); + } + } +} diff --git a/ComputerShopDatabaseImplement/Migrations/ComputerShopDatabaseModelSnapshot.cs b/ComputerShopDatabaseImplement/Migrations/ComputerShopDatabaseModelSnapshot.cs index 4214f0f..77d73aa 100644 --- a/ComputerShopDatabaseImplement/Migrations/ComputerShopDatabaseModelSnapshot.cs +++ b/ComputerShopDatabaseImplement/Migrations/ComputerShopDatabaseModelSnapshot.cs @@ -38,7 +38,7 @@ namespace ComputerShopDatabaseImplement.Migrations .IsRequired() .HasColumnType("text"); - b.Property("Cost") + b.Property("Price") .HasColumnType("double precision"); b.Property("UserId") @@ -137,7 +137,7 @@ namespace ComputerShopDatabaseImplement.Migrations NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - b.Property("Cost") + b.Property("Price") .HasColumnType("double precision"); b.Property("ProductName") diff --git a/ComputerShopDatabaseImplement/Models/Assembly.cs b/ComputerShopDatabaseImplement/Models/Assembly.cs index e0df13e..7b470ae 100644 --- a/ComputerShopDatabaseImplement/Models/Assembly.cs +++ b/ComputerShopDatabaseImplement/Models/Assembly.cs @@ -1,4 +1,5 @@ using ComputerShopContracts.BindingModels; +using ComputerShopContracts.ViewModels; using ComputerShopDataModels.Models; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -16,7 +17,7 @@ namespace ComputerShopDatabaseImplement.Models public string AssemblyName { get; private set; } = string.Empty; [Required] - public double Cost { get; private set; } + public double Price { get; private set; } [Required] public string Category { get; private set; } = string.Empty; @@ -53,7 +54,7 @@ namespace ComputerShopDatabaseImplement.Models Id = Model.Id, UserId = Model.UserId, AssemblyName = Model.AssemblyName, - Cost = Model.Cost, + Price = Model.Price, Category = Model.Category, Components = Model.AssemblyComponents.Select(x => new AssemblyComponent { @@ -63,6 +64,64 @@ namespace ComputerShopDatabaseImplement.Models }; } - // TODO: Update(), ViewModel, UpdateComponents() + public void Update(AssemblyBindingModel Model) + { + if (!string.IsNullOrEmpty(Model.AssemblyName)) + { + AssemblyName = Model.AssemblyName; + } + + if (!string.IsNullOrEmpty(Model.Category)) + { + Category = Model.Category; + } + + Price = Model.Price; + } + + public AssemblyViewModel ViewModel => new() + { + Id = Id, + UserId = UserId, + AssemblyName = AssemblyName, + Price = Price, + Category = Category, + AssemblyComponents = AssemblyComponents, + }; + + public void UpdateComponents(ComputerShopDatabase Context, AssemblyBindingModel Model) + { + var AssemblyComponents = Context.AssemblyComponents.Where(x => x.AssemblyId == Model.Id).ToList(); + if (AssemblyComponents != null && AssemblyComponents.Count > 0) + { + Context.AssemblyComponents + .RemoveRange(AssemblyComponents + .Where(x => !Model.AssemblyComponents.ContainsKey(x.ComponentId))); + Context.SaveChanges(); + + foreach (var ComponentToUpdate in AssemblyComponents) + { + ComponentToUpdate.Count = Model.AssemblyComponents[ComponentToUpdate.ComponentId].Item2; + Model.AssemblyComponents.Remove(ComponentToUpdate.ComponentId); + } + + Context.SaveChanges(); + } + + var CurrentAssembly = Context.Assemblies.First(x => x.Id == Id); + foreach (var AssemblyComponent in Model.AssemblyComponents) + { + Context.AssemblyComponents.Add(new AssemblyComponent + { + Assembly = CurrentAssembly, + Component = Context.Components.First(x => x.Id == AssemblyComponent.Key), + Count = AssemblyComponent.Value.Item2 + }); + + Context.SaveChanges(); + } + + _assemblyComponents = null; + } } } diff --git a/ComputerShopDatabaseImplement/Models/Product.cs b/ComputerShopDatabaseImplement/Models/Product.cs index 63623c1..924a19d 100644 --- a/ComputerShopDatabaseImplement/Models/Product.cs +++ b/ComputerShopDatabaseImplement/Models/Product.cs @@ -1,4 +1,5 @@ using ComputerShopContracts.BindingModels; +using ComputerShopContracts.ViewModels; using ComputerShopDataModels.Models; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -12,19 +13,19 @@ namespace ComputerShopDatabaseImplement.Models [Required] public int UserId { get; set; } + public int? ShipmentId { get; set; } + + public virtual Shipment? Shipment { get; set; } + [Required] public string ProductName { get; set; } = string.Empty; [Required] - public double Cost { get; set; } + public double Price { get; set; } [Required] public int Warranty { get; set; } - public int? ShipmentId { get; set; } - - public virtual Shipment? Shipment { get; set; } - [ForeignKey("ProductId")] public virtual List Components { get; set; } = new(); @@ -53,16 +54,74 @@ namespace ComputerShopDatabaseImplement.Models { Id = Model.Id, UserId = Model.UserId, + ShipmentId = Model.ShipmentId, ProductName = Model.ProductName, - Cost = Model.Cost, + Price = Model.Price, Warranty = Model.Warranty, Components = Model.ProductComponents.Select(x => new ProductComponent { Component = Context.Components.First(y => y.Id == x.Key), Count = x.Value.Item2 }).ToList(), - ShipmentId = Model.ShipmentId, }; } + + public void Update(ProductBindingModel Model) + { + if (!string.IsNullOrEmpty(Model.ProductName)) + { + ProductName = Model.ProductName; + } + + ShipmentId = Model.ShipmentId; + Price = Model.Price; + Warranty = Model.Warranty; + } + + public ProductViewModel ViewModel => new() + { + Id = Id, + UserId = UserId, + ShipmentId = ShipmentId, + ProviderName = Shipment?.ProviderName, + Price = Price, + Warranty = Warranty, + ProductComponents = ProductComponents, + }; + + public void UpdateComponents(ComputerShopDatabase Context, ProductBindingModel Model) + { + var ProductComponents = Context.ProductComponents.Where(x => x.ProductId == Model.Id).ToList(); + if (ProductComponents != null && ProductComponents.Count > 0) + { + Context.ProductComponents + .RemoveRange(ProductComponents + .Where(x => !Model.ProductComponents.ContainsKey(x.ComponentId))); + Context.SaveChanges(); + + foreach (var ComponentToUpdate in ProductComponents) + { + ComponentToUpdate.Count = Model.ProductComponents[ComponentToUpdate.ComponentId].Item2; + Model.ProductComponents.Remove(ComponentToUpdate.ComponentId); + } + + Context.SaveChanges(); + } + + var CurrentProduct = Context.Products.First(x => x.Id == Id); + foreach (var ProductComponent in Model.ProductComponents) + { + Context.ProductComponents.Add(new ProductComponent + { + Product = CurrentProduct, + Component = Context.Components.First(x => x.Id == ProductComponent.Key), + Count = ProductComponent.Value.Item2 + }); + + Context.SaveChanges(); + } + + _productComponents = null; + } } } diff --git a/ComputerShopDatabaseImplement/Models/Request.cs b/ComputerShopDatabaseImplement/Models/Request.cs index e9ab601..84cd5c6 100644 --- a/ComputerShopDatabaseImplement/Models/Request.cs +++ b/ComputerShopDatabaseImplement/Models/Request.cs @@ -95,7 +95,7 @@ namespace ComputerShopDatabaseImplement.Models { var currentRequest = context.Requests.First(x => x.Id == Id); //стоимость сборки, связанной с заявкой (или 0, если заявка не связана со сборкой) - double cost_of_assembly = (currentRequest.Assembly.Cost != null) ? currentRequest.Assembly.Cost : 0; + double cost_of_assembly = (currentRequest.Assembly.Price != null) ? currentRequest.Assembly.Price : 0; var requestOrders = context.RequestOrders.Where(x => x.RequestId == model.Id).ToList(); @@ -134,7 +134,7 @@ namespace ComputerShopDatabaseImplement.Models public void ConnectAssembly(ComputerShopDatabase context, RequestBindingModel model) { //стоимость старой сборки (или 0, если её не было) - double cost_of_old_assembly = (Assembly.Cost != null) ? Assembly.Cost : 0; + double cost_of_old_assembly = (Assembly.Price != null) ? Assembly.Price : 0; AssemblyId = model.AssemblyId; Assembly = context.Assemblies.First(x => x.Id == model.AssemblyId); @@ -145,7 +145,7 @@ namespace ComputerShopDatabaseImplement.Models //вычитание из стоимости заказа старой сборки connectedOrder.ChangeSum(-cost_of_old_assembly); //прибавление стоимости новой сборки - connectedOrder.ChangeSum(Assembly.Cost); + connectedOrder.ChangeSum(Assembly.Price); context.SaveChanges(); } }