diff --git a/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Migrations/ComputerHardwareStoreDBContextModelSnapshot.cs b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Migrations/ComputerHardwareStoreDBContextModelSnapshot.cs
new file mode 100644
index 0000000..2074f70
--- /dev/null
+++ b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Migrations/ComputerHardwareStoreDBContextModelSnapshot.cs
@@ -0,0 +1,544 @@
+//
+using System;
+using ComputerHardwareStoreDatabaseImplement;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace ComputerHardwareStoreDatabaseImplement.Migrations
+{
+ [DbContext(typeof(ComputerHardwareStoreDBContext))]
+ partial class ComputerHardwareStoreDBContextModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.4")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Build", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Price")
+ .HasColumnType("double precision");
+
+ b.Property("VendorId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("VendorId");
+
+ b.ToTable("Builds");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.BuildComponent", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BuildId")
+ .HasColumnType("integer");
+
+ b.Property("ComponentId")
+ .HasColumnType("integer");
+
+ b.Property("Count")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BuildId");
+
+ b.HasIndex("ComponentId");
+
+ b.ToTable("BuildComponents");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Comment", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BuildId")
+ .HasColumnType("integer");
+
+ b.Property("Date")
+ .HasColumnType("timestamp without time zone");
+
+ b.Property("Text")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BuildId");
+
+ b.ToTable("Comments");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Component", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Cost")
+ .HasColumnType("double precision");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("StoreKeeperId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("StoreKeeperId");
+
+ b.ToTable("Components");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Order", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("DateCreate")
+ .HasColumnType("timestamp without time zone");
+
+ b.Property("DateImplement")
+ .HasColumnType("timestamp without time zone");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("Sum")
+ .HasColumnType("double precision");
+
+ b.HasKey("Id");
+
+ b.ToTable("Orders");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.OrderProduct", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Count")
+ .HasColumnType("integer");
+
+ b.Property("OrderId")
+ .HasColumnType("integer");
+
+ b.Property("ProductId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrderId");
+
+ b.HasIndex("ProductId");
+
+ b.ToTable("OrderProducts");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Product", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Price")
+ .HasColumnType("double precision");
+
+ b.Property("StoreKeeperId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("StoreKeeperId");
+
+ b.ToTable("Products");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.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("ComputerHardwareStoreDatabaseImplement.Models.Purchase", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Cost")
+ .HasColumnType("double precision");
+
+ b.Property("DateCreate")
+ .HasColumnType("timestamp without time zone");
+
+ b.Property("DateImplement")
+ .HasColumnType("timestamp without time zone");
+
+ b.Property("VendorId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("VendorId");
+
+ b.ToTable("Purchases");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.PurchaseBuild", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BuildId")
+ .HasColumnType("integer");
+
+ b.Property("Count")
+ .HasColumnType("integer");
+
+ b.Property("PurchaseId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BuildId");
+
+ b.HasIndex("PurchaseId");
+
+ b.ToTable("PurchaseBuilds");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.PurchaseProduct", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Count")
+ .HasColumnType("integer");
+
+ b.Property("ProductId")
+ .HasColumnType("integer");
+
+ b.Property("PurchaseId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ProductId");
+
+ b.HasIndex("PurchaseId");
+
+ b.ToTable("PurchaseProducts");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.StoreKeeper", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Login")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("StoreKeepers");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Vendor", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Login")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Password")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Vendors");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Build", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Vendor", "Vendor")
+ .WithMany("Builds")
+ .HasForeignKey("VendorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Vendor");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.BuildComponent", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Build", "Build")
+ .WithMany("Components")
+ .HasForeignKey("BuildId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Component", "Component")
+ .WithMany()
+ .HasForeignKey("ComponentId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Build");
+
+ b.Navigation("Component");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Comment", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Build", "Build")
+ .WithMany()
+ .HasForeignKey("BuildId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Build");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Component", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.StoreKeeper", "StoreKeeperЗЛ")
+ .WithMany("Components")
+ .HasForeignKey("StoreKeeperId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("StoreKeeperЗЛ");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.OrderProduct", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Order", "Order")
+ .WithMany("Products")
+ .HasForeignKey("OrderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Product", "Product")
+ .WithMany()
+ .HasForeignKey("ProductId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Order");
+
+ b.Navigation("Product");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Product", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.StoreKeeper", null)
+ .WithMany("Products")
+ .HasForeignKey("StoreKeeperId");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.ProductComponent", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Component", "Component")
+ .WithMany("ProductComponents")
+ .HasForeignKey("ComponentId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Product", "Product")
+ .WithMany("Components")
+ .HasForeignKey("ProductId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Component");
+
+ b.Navigation("Product");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Purchase", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Vendor", null)
+ .WithMany("Purchases")
+ .HasForeignKey("VendorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.PurchaseBuild", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Build", "Build")
+ .WithMany()
+ .HasForeignKey("BuildId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Purchase", "Purchase")
+ .WithMany("Builds")
+ .HasForeignKey("PurchaseId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Build");
+
+ b.Navigation("Purchase");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.PurchaseProduct", b =>
+ {
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Product", "Product")
+ .WithMany()
+ .HasForeignKey("ProductId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("ComputerHardwareStoreDatabaseImplement.Models.Purchase", "Purchase")
+ .WithMany("Products")
+ .HasForeignKey("PurchaseId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Product");
+
+ b.Navigation("Purchase");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Build", b =>
+ {
+ b.Navigation("Components");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Component", b =>
+ {
+ b.Navigation("ProductComponents");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Order", b =>
+ {
+ b.Navigation("Products");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Product", b =>
+ {
+ b.Navigation("Components");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Purchase", b =>
+ {
+ b.Navigation("Builds");
+
+ b.Navigation("Products");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.StoreKeeper", b =>
+ {
+ b.Navigation("Components");
+
+ b.Navigation("Products");
+ });
+
+ modelBuilder.Entity("ComputerHardwareStoreDatabaseImplement.Models.Vendor", b =>
+ {
+ b.Navigation("Builds");
+
+ b.Navigation("Purchases");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Build.cs b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Build.cs
new file mode 100644
index 0000000..5b2ae2d
--- /dev/null
+++ b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Build.cs
@@ -0,0 +1,87 @@
+using ComputerHardwareStoreContracts.BindingModels;
+using ComputerHardwareStoreContracts.ViewModels;
+using ComputerHardwareStoreDataModels.Models;
+using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace ComputerHardwareStoreDatabaseImplement.Models
+{
+ public class Build : IBuildModel
+ {
+ public int Id { get; set; }
+ [Required]
+ public string Name { get; set; } = string.Empty;
+ [Required]
+ public double Price { get; set; }
+ [NotMapped]
+ private Dictionary? _buildComponents = null;
+ [NotMapped]
+ public Dictionary BuildComponents
+ {
+ get
+ {
+ if (_buildComponents == null)
+ {
+ _buildComponents = Components
+ .ToDictionary(bc => bc.ComponentId, bc =>
+ (bc.Component as IComponentModel, bc.Count));
+ }
+ return _buildComponents;
+ }
+ }
+ [ForeignKey("BuildId")]
+ public virtual List Components { get; set; } = new();
+ [ForeignKey("BuildId")]
+ public virtual List Comments { get; set; } = new();
+ [NotMapped]
+ List IBuildModel.Comments => Comments.Select(c => c as ICommentModel).ToList();
+
+ public virtual Vendor Vendor { get; private set; } = new();
+ IVendorModel IBuildModel.Vendor => Vendor as IVendorModel;
+
+ public static Build? Create(ComputerHardwareStoreDBContext context, BuildBindingModel model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+ return new()
+ {
+ Id = model.Id,
+ Name = model.Name,
+ Price = model.Price,
+ Vendor = context.Vendors.First(v => v.Id == model.Vendor.Id),
+ Components = context.Components
+ .Where(c => model.BuildComponents.ContainsKey(c.Id))
+ .Select(c => new BuildComponent()
+ {
+ BuildId = model.Id,
+ ComponentId = c.Id,
+ Component = c,
+ Count = model.BuildComponents[c.Id].Item2
+ }).ToList()
+ };
+ }
+
+ public void Update(BuildBindingModel model)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ Name = string.IsNullOrEmpty(model.Name) ? Name : model.Name;
+ Price = model.Price;
+ }
+
+ public BuildViewModel GetViewModel => new()
+ {
+ Id = Id,
+ Name = Name,
+ Price = Price,
+ Vendor = Vendor,
+ Comments = Comments.Select(c => c as ICommentModel).ToList(),
+ BuildComponents = BuildComponents
+ };
+ }
+}
diff --git a/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Comment.cs b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Comment.cs
new file mode 100644
index 0000000..98e165c
--- /dev/null
+++ b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Comment.cs
@@ -0,0 +1,49 @@
+using ComputerHardwareStoreContracts.BindingModels;
+using ComputerHardwareStoreContracts.ViewModels;
+using ComputerHardwareStoreDataModels.Models;
+using System.ComponentModel.DataAnnotations;
+
+namespace ComputerHardwareStoreDatabaseImplement.Models
+{
+ public class Comment : ICommentModel
+ {
+ public int Id { get; set; }
+ [Required]
+ public DateTime Date { get; set; }
+ [Required]
+ public string Text { get; set; } = string.Empty;
+ [Required]
+ public int BuildId { get; set; }
+ public virtual Build Build { get; set; } = new();
+ public static Comment? Create(CommentBindingModel model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+ return new()
+ {
+ Id = model.Id,
+ Date = model.Date,
+ Text = model.Text,
+ BuildId = model.BuildId,
+ };
+ }
+
+ public void Update(CommentBindingModel model)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ Text = model.Text;
+ }
+
+ public CommentViewModel GetViewModel => new()
+ {
+ Id = Id,
+ Date = Date,
+ Text = Text,
+ };
+ }
+}
diff --git a/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Order.cs b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Order.cs
new file mode 100644
index 0000000..b03e97e
--- /dev/null
+++ b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Order.cs
@@ -0,0 +1,82 @@
+using ComputerHardwareStoreContracts.BindingModels;
+using ComputerHardwareStoreContracts.ViewModels;
+using ComputerHardwareStoreDataModels.Enums;
+using ComputerHardwareStoreDataModels.Models;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace ComputerHardwareStoreDatabaseImplement.Models
+{
+ public class Order : IOrderModel
+ {
+ public int Id { get; private set; }
+ [Required]
+ public double Sum { get; set; }
+ [Required]
+ public OrderStatus Status { get; set; } = OrderStatus.Неизвестен;
+ [Required]
+ public DateTime DateCreate { get; set; } = DateTime.Now;
+ public DateTime? DateImplement { get; set; }
+
+ private Dictionary? _orderProducts = null;
+ [NotMapped]
+ public Dictionary OrderProducts
+ {
+ get
+ {
+ if (_orderProducts == null)
+ {
+ _orderProducts = Products
+ .ToDictionary(
+ op => op.ProductId,
+ op => (op.Product as IProductModel, op.Count));
+ }
+ return _orderProducts;
+ }
+ }
+ [ForeignKey("OrderId")]
+ public virtual List Products { get; set; } = new();
+ public static Order? Create(ComputerHardwareStoreDBContext context, OrderBindingModel model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+ return new Order()
+ {
+ Id = model.Id,
+ Sum = model.Sum,
+ Status = model.Status,
+ DateCreate = model.DateCreate,
+ DateImplement = model.DateImplement,
+ Products = context.Products
+ .Where(p => model.OrderProducts.ContainsKey(p.Id))
+ .Select(p => new OrderProduct()
+ {
+ OrderId = model.Id,
+ ProductId = p.Id,
+ Product = p,
+ Count = model.OrderProducts[p.Id].Item2
+ })
+ .ToList()
+ };
+ }
+ public void Update(OrderBindingModel model)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ Status = model.Status;
+ DateImplement = model.DateImplement;
+ }
+ public OrderViewModel GetViewModel => new()
+ {
+ Id = Id,
+ Sum = Sum,
+ Status = Status,
+ DateCreate = DateCreate,
+ DateImplement = DateImplement,
+ };
+ }
+}
\ No newline at end of file
diff --git a/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Product.cs b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Product.cs
new file mode 100644
index 0000000..c995ce7
--- /dev/null
+++ b/ComputerHardwareStore/ComputerHardwareStoreDatabaseImplement/Models/Product.cs
@@ -0,0 +1,96 @@
+using ComputerHardwareStoreContracts.BindingModels;
+using ComputerHardwareStoreContracts.ViewModels;
+using ComputerHardwareStoreDataModels.Models;
+using Microsoft.EntityFrameworkCore;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+
+namespace ComputerHardwareStoreDatabaseImplement.Models
+{
+ public class Product : IProductModel
+ {
+ public int Id { get; set; }
+ [Required]
+ public string Name { get; set; } = string.Empty;
+ [Required]
+ public double Price { get; set; }
+ private Dictionary? _productComponents = null;
+ [NotMapped]
+ public Dictionary ProductComponents
+ {
+ get
+ {
+ if (_productComponents == null)
+ {
+ _productComponents = Components
+ .ToDictionary(c => c.ComponentId, c => (c.Component as IComponentModel, c.Count));
+ }
+ return _productComponents;
+ }
+ }
+ [ForeignKey("ProductId")]
+ public virtual List Components { get; set; } = new();
+ public static Product Create(ComputerHardwareStoreDBContext context, ProductBindingModel model)
+ {
+ return new Product()
+ {
+ Id = model.Id,
+ Name = model.Name,
+ Price = model.Price,
+ Components = context.Components
+ .Where(c => model.ProductComponents.ContainsKey(c.Id))
+ .Select(c => new ProductComponent()
+ {
+ ProductId = model.Id,
+ ComponentId = c.Id,
+ Component = c,
+ Count = model.ProductComponents[c.Id].Item2
+ }).ToList(),
+ };
+ }
+ public void Update(ProductBindingModel model)
+ {
+ Name = string.IsNullOrEmpty(model.Name) ? Name : model.Name;
+ Price = model.Price;
+
+ }
+ public ProductViewModel GetViewModel => new()
+ {
+ Id = Id,
+ Name = Name,
+ Price = Price,
+ ProductComponents = ProductComponents
+ };
+
+ public static void UpdateComponents(ComputerHardwareStoreDBContext context, ProductBindingModel model)
+ {
+ var productComponents = context.ProductComponents
+ .Where(pc => pc.ProductId == model.Id)
+ .ToList();
+ if (productComponents.Count != 0 && productComponents.Count > 0)
+ {
+ // удалили те, которых нет в модели
+ context.ProductComponents
+ .Where(pc => !model.ProductComponents.ContainsKey(pc.ComponentId))
+ .ExecuteDelete();
+ // обновили количество у существующих записей
+ productComponents
+ .ForEach(updateComponent =>
+ {
+ updateComponent.Count = model.ProductComponents[updateComponent.ComponentId].Item2;
+ model.ProductComponents.Remove(updateComponent.ComponentId);
+ });
+ }
+ // добавили новые
+ context.ProductComponents
+ .AddRange(model.ProductComponents.Values
+ .Select(val => new ProductComponent()
+ {
+ ProductId = model.Id,
+ ComponentId = val.Item1.Id,
+ Count = val.Item2
+ }));
+ context.SaveChanges();
+ }
+ }
+}
diff --git a/ComputerHardwareStore/ComputerHardwareStoreREST/ComputerHardwareStoreREST.csproj b/ComputerHardwareStore/ComputerHardwareStoreREST/ComputerHardwareStoreREST.csproj
new file mode 100644
index 0000000..8777ec2
--- /dev/null
+++ b/ComputerHardwareStore/ComputerHardwareStoreREST/ComputerHardwareStoreREST.csproj
@@ -0,0 +1,26 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
diff --git a/ComputerHardwareStore/ComputerHardwareStoreREST/Program.cs b/ComputerHardwareStore/ComputerHardwareStoreREST/Program.cs
new file mode 100644
index 0000000..fb6235b
--- /dev/null
+++ b/ComputerHardwareStore/ComputerHardwareStoreREST/Program.cs
@@ -0,0 +1,41 @@
+using ComputerHardwareStoreContracts.StorageContracts;
+using ComputerHardwareStoreDatabaseImplement;
+using ComputerHardwareStoreDatabaseImplement.Implements;
+using ComputerHardwareStoreREST;
+using Microsoft.EntityFrameworkCore;
+
+var builder = WebApplication.CreateBuilder(args);
+
+// Add services to the container.
+
+builder.Services.AddControllers();
+// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
+builder.Services.AddEndpointsApiExplorer();
+builder.Services.AddSwaggerGen();
+
+// получаем строку подключения из файла конфигурации
+//DBSetting.ConectionString = builder.Configuration.GetConnectionString("DefaultConnection");
+
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+builder.Services.AddSingleton();
+
+var app = builder.Build();
+
+// Configure the HTTP request pipeline.
+if (app.Environment.IsDevelopment())
+{
+ app.UseSwagger();
+ app.UseSwaggerUI();
+}
+
+app.UseAuthorization();
+
+app.MapControllers();
+
+app.Run();