From c67ee5f3926b41caf7051c7bc37f9d8df49f9d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=9C=D0=B0=D0=BB?= =?UTF-8?q?=D0=B0=D1=84=D0=B5=D0=B5=D0=B2?= Date: Sat, 23 Mar 2024 18:19:44 +0400 Subject: [PATCH] =?UTF-8?q?Lab3=20+=20=D0=BD=D0=BE=D0=B2=D1=8B=D0=B9=20sln?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- JewelryStore/JewelryStore/JewelryStore.csproj | 7 + JewelryStore/JewelryStore/JewelryStore.sln | 6 + .../JewelryStoreBusinessLogic.csproj | 4 + .../JewelryStoreContracts.csproj | 7 + .../Implements/ComponentStorage.cs | 80 +++++++++ .../Implements/JewelStorage.cs | 94 ++++++++++ .../Implements/OrderStorage.cs | 94 ++++++++++ .../JewelryStoreDatabase.cs | 26 +++ .../JewelryStoreDatabaseImplement.csproj | 23 +++ .../20240310110723_InitialCreate.Designer.cs | 170 ++++++++++++++++++ .../20240310110723_InitialCreate.cs | 122 +++++++++++++ .../JewelryStoreDatabaseModelSnapshot.cs | 168 +++++++++++++++++ .../Models/Component.cs | 61 +++++++ .../Models/Jewel.cs | 97 ++++++++++ .../Models/JewelComponent.cs | 22 +++ .../Models/Order.cs | 68 +++++++ .../JewelryStoreListImplement.csproj | 7 + .../JewerlyStoreDataModels.csproj | 7 + .../JewerlyStoreFileImplement.csproj | 7 + .../JewerlyStoreView/JewerlyStoreView.csproj | 10 ++ .../JewerlyStoreView/JewerlyStoreView.sln | 58 ++++++ JewelryStore/JewerlyStoreView/Program.cs | 2 +- 22 files changed, 1139 insertions(+), 1 deletion(-) create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Implements/ComponentStorage.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Implements/JewelStorage.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Implements/OrderStorage.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/JewelryStoreDatabase.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/JewelryStoreDatabaseImplement.csproj create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Migrations/20240310110723_InitialCreate.Designer.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Migrations/20240310110723_InitialCreate.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Migrations/JewelryStoreDatabaseModelSnapshot.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Models/Component.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Models/Jewel.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Models/JewelComponent.cs create mode 100644 JewelryStore/JewelryStoreDatabaseImplement/Models/Order.cs create mode 100644 JewelryStore/JewerlyStoreView/JewerlyStoreView.sln diff --git a/JewelryStore/JewelryStore/JewelryStore.csproj b/JewelryStore/JewelryStore/JewelryStore.csproj index c78c9c7..4a7c602 100644 --- a/JewelryStore/JewelryStore/JewelryStore.csproj +++ b/JewelryStore/JewelryStore/JewelryStore.csproj @@ -6,4 +6,11 @@ enable + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/JewelryStore/JewelryStore/JewelryStore.sln b/JewelryStore/JewelryStore/JewelryStore.sln index 596352c..11e7973 100644 --- a/JewelryStore/JewelryStore/JewelryStore.sln +++ b/JewelryStore/JewelryStore/JewelryStore.sln @@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewerlyStoreView", "..\Jewe EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewerlyStoreFileImplement", "..\JewerlyStoreFileImplement\JewerlyStoreFileImplement.csproj", "{CBCAFAE3-4CF6-43BB-A053-97FA6FD7A90B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JewelryStoreDatabaseImplement", "..\JewelryStoreDatabaseImplement\JewelryStoreDatabaseImplement.csproj", "{B60549DE-BD6D-412E-8318-30220C43B061}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -51,6 +53,10 @@ Global {CBCAFAE3-4CF6-43BB-A053-97FA6FD7A90B}.Debug|Any CPU.Build.0 = Debug|Any CPU {CBCAFAE3-4CF6-43BB-A053-97FA6FD7A90B}.Release|Any CPU.ActiveCfg = Release|Any CPU {CBCAFAE3-4CF6-43BB-A053-97FA6FD7A90B}.Release|Any CPU.Build.0 = Release|Any CPU + {B60549DE-BD6D-412E-8318-30220C43B061}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B60549DE-BD6D-412E-8318-30220C43B061}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B60549DE-BD6D-412E-8318-30220C43B061}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B60549DE-BD6D-412E-8318-30220C43B061}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/JewelryStore/JewelryStoreBusinessLogic/JewelryStoreBusinessLogic.csproj b/JewelryStore/JewelryStoreBusinessLogic/JewelryStoreBusinessLogic.csproj index cb90ecb..1a1f23e 100644 --- a/JewelryStore/JewelryStoreBusinessLogic/JewelryStoreBusinessLogic.csproj +++ b/JewelryStore/JewelryStoreBusinessLogic/JewelryStoreBusinessLogic.csproj @@ -7,6 +7,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/JewelryStore/JewelryStoreContracts/JewelryStoreContracts.csproj b/JewelryStore/JewelryStoreContracts/JewelryStoreContracts.csproj index e4c7f5b..fa5fd76 100644 --- a/JewelryStore/JewelryStoreContracts/JewelryStoreContracts.csproj +++ b/JewelryStore/JewelryStoreContracts/JewelryStoreContracts.csproj @@ -6,6 +6,13 @@ enable + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Implements/ComponentStorage.cs b/JewelryStore/JewelryStoreDatabaseImplement/Implements/ComponentStorage.cs new file mode 100644 index 0000000..a77bfb3 --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Implements/ComponentStorage.cs @@ -0,0 +1,80 @@ +using JewelryStoreContracts.BindingModels; +using JewelryStoreContracts.SearchModels; +using JewelryStoreContracts.StoragesContracts; +using JewelryStoreContracts.ViewModels; +using JewelryStoreDatabaseImplement.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JewelryStoreDatabaseImplement.Implements +{ + public class ComponentStorage : IComponentStorage + { + public List GetFullList() + { + using var context = new JewelryStoreDatabase(); + return context.Components.Select(x => x.GetViewModel).ToList(); + } + + public List GetFilteredList(ComponentSearchModel model) + { + if (string.IsNullOrEmpty(model.ComponentName)) + { + return new(); + } + using var context = new JewelryStoreDatabase(); + return context.Components.Where(x => x.ComponentName.Contains(model.ComponentName)).Select(x => x.GetViewModel).ToList(); + } + + public ComponentViewModel? GetElement(ComponentSearchModel model) + { + if (string.IsNullOrEmpty(model.ComponentName) && !model.Id.HasValue) + { + return null; + } + using var context = new JewelryStoreDatabase(); + return context.Components.FirstOrDefault(x => (!string.IsNullOrEmpty(model.ComponentName) && x.ComponentName == model.ComponentName) || + (model.Id.HasValue && x.Id == model.Id))?.GetViewModel; + } + + public ComponentViewModel? Insert(ComponentBindingModel model) + { + var newComponent = Component.Create(model); + if (newComponent == null) + { + return null; + } + using var context = new JewelryStoreDatabase(); + context.Components.Add(newComponent); + context.SaveChanges(); + return newComponent.GetViewModel; + } + public ComponentViewModel? Update(ComponentBindingModel model) + { + using var context = new JewelryStoreDatabase(); + var component = context.Components.FirstOrDefault(x => x.Id == model.Id); + if (component == null) + { + return null; + } + component.Update(model); + context.SaveChanges(); + return component.GetViewModel; + } + public ComponentViewModel? Delete(ComponentBindingModel model) + { + using var context = new JewelryStoreDatabase(); + var element = context.Components.FirstOrDefault(rec => rec.Id == model.Id); + if (element != null) + { + context.Components.Remove(element); + context.SaveChanges(); + return element.GetViewModel; + } + return null; + } + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Implements/JewelStorage.cs b/JewelryStore/JewelryStoreDatabaseImplement/Implements/JewelStorage.cs new file mode 100644 index 0000000..8f78d3e --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Implements/JewelStorage.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JewelryStoreContracts.BindingModels; +using JewelryStoreContracts.SearchModels; +using JewelryStoreContracts.StoragesContracts; +using JewelryStoreContracts.ViewModels; +using JewelryStoreDatabaseImplement.Models; +using Microsoft.EntityFrameworkCore; + +namespace JewelryStoreDatabaseImplement.Implements +{ + public class JewelStorage : IJewelStorage + { + public List GetFullList() + { + using var context = new JewelryStoreDatabase(); + return context.Jewels.Include(x => x.Components).ThenInclude(x => x.Component).ToList().Select(x => x.GetViewModel).ToList(); + } + public List GetFilteredList(JewelSearchModel model) + { + if (string.IsNullOrEmpty(model.JewelName)) + { + return new(); + } + using var context = new JewelryStoreDatabase(); + return context.Jewels.Include(x => x.Components).ThenInclude(x => x.Component) + .Where(x => x.JewelName.Contains(model.JewelName)).ToList().Select(x => x.GetViewModel).ToList(); + } + public JewelViewModel? GetElement(JewelSearchModel model) + { + if (string.IsNullOrEmpty(model.JewelName) && !model.Id.HasValue) + { + return null; + } + using var context = new JewelryStoreDatabase(); + return context.Jewels.Include(x => x.Components).ThenInclude(x => x.Component).FirstOrDefault(x => (!string.IsNullOrEmpty(model.JewelName) && + x.JewelName == model.JewelName) || (model.Id.HasValue && x.Id == model.Id))?.GetViewModel; + } + public JewelViewModel? Insert(JewelBindingModel model) + { + using var context = new JewelryStoreDatabase(); + var newProduct = Jewel.Create(context, model); + if (newProduct == null) + { + return null; + } + context.Jewels.Add(newProduct); + context.SaveChanges(); + return newProduct.GetViewModel; + } + public JewelViewModel? Update(JewelBindingModel model) + { + using var context = new JewelryStoreDatabase(); + using var transaction = context.Database.BeginTransaction(); + try + { + var product = context.Jewels.FirstOrDefault(rec => + rec.Id == model.Id); + if (product == null) + { + return null; + } + product.Update(model); + context.SaveChanges(); + product.UpdateComponents(context, model); + transaction.Commit(); + return product.GetViewModel; + } + catch + { + transaction.Rollback(); + throw; + } + } + public JewelViewModel? Delete(JewelBindingModel model) + { + using var context = new JewelryStoreDatabase(); + var element = context.Jewels + .Include(x => x.Components) + .FirstOrDefault(rec => rec.Id == model.Id); + if (element != null) + { + context.Jewels.Remove(element); + context.SaveChanges(); + return element.GetViewModel; + } + return null; + } + + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Implements/OrderStorage.cs b/JewelryStore/JewelryStoreDatabaseImplement/Implements/OrderStorage.cs new file mode 100644 index 0000000..0373351 --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Implements/OrderStorage.cs @@ -0,0 +1,94 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using JewelryStoreContracts.BindingModels; +using JewelryStoreContracts.SearchModels; +using JewelryStoreContracts.StoragesContracts; +using JewelryStoreContracts.ViewModels; +using JewelryStoreDatabaseImplement.Models; + +namespace JewelryStoreDatabaseImplement.Implements +{ + public class OrderStorage : IOrderStorage + { + public List GetFullList() + { + using var context = new JewelryStoreDatabase(); + return context.Orders + .Select(x => AccessJewelStorage(x.GetViewModel, context)) + .ToList(); + } + public List GetFilteredList(OrderSearchModel model) + { + if (!model.Id.HasValue) + { + return new(); + } + using var context = new JewelryStoreDatabase(); + return context.Orders + .Where(x => x.Id == model.Id) + .Select(x => AccessJewelStorage(x.GetViewModel, context)) + .ToList(); + } + public OrderViewModel? GetElement(OrderSearchModel model) + { + if (!model.Id.HasValue) + { + return new(); + } + using var context = new JewelryStoreDatabase(); + return AccessJewelStorage(context.Orders.FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)?.GetViewModel, context); + } + public OrderViewModel? Insert(OrderBindingModel model) + { + var newOrder = Order.Create(model); + if (newOrder == null) + { + return null; + } + using var context = new JewelryStoreDatabase(); + context.Orders.Add(newOrder); + context.SaveChanges(); + return AccessJewelStorage(newOrder.GetViewModel, context); + } + public OrderViewModel? Update(OrderBindingModel model) + { + using var context = new JewelryStoreDatabase(); + var order = context.Orders.FirstOrDefault(x => x.Id == model.Id); + if (order == null) + { + return null; + } + order.Update(model); + context.SaveChanges(); + return AccessJewelStorage(order.GetViewModel, context); + } + public OrderViewModel? Delete(OrderBindingModel model) + { + using var context = new JewelryStoreDatabase(); + var element = context.Orders.FirstOrDefault(rec => rec.Id == model.Id); + if (element != null) + { + context.Orders.Remove(element); + context.SaveChanges(); + return AccessJewelStorage(element.GetViewModel, context); + } + return null; + } + static OrderViewModel AccessJewelStorage(OrderViewModel model, JewelryStoreDatabase context) + { + if (model == null) + { + return null; + } + var jewel = context.Jewels.FirstOrDefault(x => x.Id == model.JewelId); + if (jewel == null) { + return null; + } + model.JewelName = jewel.JewelName; + return model; + } + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/JewelryStoreDatabase.cs b/JewelryStore/JewelryStoreDatabaseImplement/JewelryStoreDatabase.cs new file mode 100644 index 0000000..2bbf849 --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/JewelryStoreDatabase.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using JewelryStoreDatabaseImplement.Models; + +namespace JewelryStoreDatabaseImplement +{ + public class JewelryStoreDatabase : DbContext + { + protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) + { + if (optionsBuilder.IsConfigured == false) + { + optionsBuilder.UseSqlServer(@"Data Source=localhost\SQLEXPRESS;Initial Catalog=JewelryStoreDatabaseFull;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True"); + } + base.OnConfiguring(optionsBuilder); + } + public virtual DbSet Components { set; get; } + public virtual DbSet Jewels { set; get; } + public virtual DbSet JewelComponents { set; get; } + public virtual DbSet Orders { set; get; } + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/JewelryStoreDatabaseImplement.csproj b/JewelryStore/JewelryStoreDatabaseImplement/JewelryStoreDatabaseImplement.csproj new file mode 100644 index 0000000..e501829 --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/JewelryStoreDatabaseImplement.csproj @@ -0,0 +1,23 @@ + + + + net6.0 + enable + enable + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Migrations/20240310110723_InitialCreate.Designer.cs b/JewelryStore/JewelryStoreDatabaseImplement/Migrations/20240310110723_InitialCreate.Designer.cs new file mode 100644 index 0000000..1965862 --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Migrations/20240310110723_InitialCreate.Designer.cs @@ -0,0 +1,170 @@ +// +using System; +using JewelryStoreDatabaseImplement; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace JewelryStoreDatabaseImplement.Migrations +{ + [DbContext(typeof(JewelryStoreDatabase))] + [Migration("20240310110723_InitialCreate")] + partial class InitialCreate + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.27") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Component", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ComponentName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cost") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Components"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Jewel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("JewelName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Jewels"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.JewelComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ComponentId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("JewelId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ComponentId"); + + b.HasIndex("JewelId"); + + b.ToTable("JewelComponents"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateImplement") + .HasColumnType("datetime2"); + + b.Property("JewelId") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Sum") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("JewelId"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.JewelComponent", b => + { + b.HasOne("JewelryStoreDatabaseImplement.Models.Component", "Component") + .WithMany("JewelComponents") + .HasForeignKey("ComponentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JewelryStoreDatabaseImplement.Models.Jewel", "Jewel") + .WithMany("Components") + .HasForeignKey("JewelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Component"); + + b.Navigation("Jewel"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Order", b => + { + b.HasOne("JewelryStoreDatabaseImplement.Models.Jewel", "Jewel") + .WithMany("Orders") + .HasForeignKey("JewelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Jewel"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Component", b => + { + b.Navigation("JewelComponents"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Jewel", b => + { + b.Navigation("Components"); + + b.Navigation("Orders"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Migrations/20240310110723_InitialCreate.cs b/JewelryStore/JewelryStoreDatabaseImplement/Migrations/20240310110723_InitialCreate.cs new file mode 100644 index 0000000..f57eb5f --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Migrations/20240310110723_InitialCreate.cs @@ -0,0 +1,122 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace JewelryStoreDatabaseImplement.Migrations +{ + public partial class InitialCreate : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Components", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ComponentName = table.Column(type: "nvarchar(max)", nullable: false), + Cost = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Components", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Jewels", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + JewelName = table.Column(type: "nvarchar(max)", nullable: false), + Price = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Jewels", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "JewelComponents", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + JewelId = table.Column(type: "int", nullable: false), + ComponentId = table.Column(type: "int", nullable: false), + Count = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_JewelComponents", x => x.Id); + table.ForeignKey( + name: "FK_JewelComponents_Components_ComponentId", + column: x => x.ComponentId, + principalTable: "Components", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_JewelComponents_Jewels_JewelId", + column: x => x.JewelId, + principalTable: "Jewels", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Orders", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + JewelId = table.Column(type: "int", nullable: false), + Count = table.Column(type: "int", nullable: false), + Sum = table.Column(type: "float", nullable: false), + Status = table.Column(type: "int", nullable: false), + DateCreate = table.Column(type: "datetime2", nullable: false), + DateImplement = table.Column(type: "datetime2", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Orders", x => x.Id); + table.ForeignKey( + name: "FK_Orders_Jewels_JewelId", + column: x => x.JewelId, + principalTable: "Jewels", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_JewelComponents_ComponentId", + table: "JewelComponents", + column: "ComponentId"); + + migrationBuilder.CreateIndex( + name: "IX_JewelComponents_JewelId", + table: "JewelComponents", + column: "JewelId"); + + migrationBuilder.CreateIndex( + name: "IX_Orders_JewelId", + table: "Orders", + column: "JewelId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "JewelComponents"); + + migrationBuilder.DropTable( + name: "Orders"); + + migrationBuilder.DropTable( + name: "Components"); + + migrationBuilder.DropTable( + name: "Jewels"); + } + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Migrations/JewelryStoreDatabaseModelSnapshot.cs b/JewelryStore/JewelryStoreDatabaseImplement/Migrations/JewelryStoreDatabaseModelSnapshot.cs new file mode 100644 index 0000000..7a7099f --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Migrations/JewelryStoreDatabaseModelSnapshot.cs @@ -0,0 +1,168 @@ +// +using System; +using JewelryStoreDatabaseImplement; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace JewelryStoreDatabaseImplement.Migrations +{ + [DbContext(typeof(JewelryStoreDatabase))] + partial class JewelryStoreDatabaseModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.27") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Component", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ComponentName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Cost") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Components"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Jewel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("JewelName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Price") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.ToTable("Jewels"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.JewelComponent", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("ComponentId") + .HasColumnType("int"); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("JewelId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ComponentId"); + + b.HasIndex("JewelId"); + + b.ToTable("JewelComponents"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Order", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"), 1L, 1); + + b.Property("Count") + .HasColumnType("int"); + + b.Property("DateCreate") + .HasColumnType("datetime2"); + + b.Property("DateImplement") + .HasColumnType("datetime2"); + + b.Property("JewelId") + .HasColumnType("int"); + + b.Property("Status") + .HasColumnType("int"); + + b.Property("Sum") + .HasColumnType("float"); + + b.HasKey("Id"); + + b.HasIndex("JewelId"); + + b.ToTable("Orders"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.JewelComponent", b => + { + b.HasOne("JewelryStoreDatabaseImplement.Models.Component", "Component") + .WithMany("JewelComponents") + .HasForeignKey("ComponentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("JewelryStoreDatabaseImplement.Models.Jewel", "Jewel") + .WithMany("Components") + .HasForeignKey("JewelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Component"); + + b.Navigation("Jewel"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Order", b => + { + b.HasOne("JewelryStoreDatabaseImplement.Models.Jewel", "Jewel") + .WithMany("Orders") + .HasForeignKey("JewelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Jewel"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Component", b => + { + b.Navigation("JewelComponents"); + }); + + modelBuilder.Entity("JewelryStoreDatabaseImplement.Models.Jewel", b => + { + b.Navigation("Components"); + + b.Navigation("Orders"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Models/Component.cs b/JewelryStore/JewelryStoreDatabaseImplement/Models/Component.cs new file mode 100644 index 0000000..14f277f --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Models/Component.cs @@ -0,0 +1,61 @@ +using JewelryStoreContracts.BindingModels; +using JewelryStoreContracts.ViewModels; +using JewerlyStoreDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JewelryStoreDatabaseImplement.Models +{ + public class Component : IComponentModel + { + public int Id { get; private set; } + [Required] + public string ComponentName { get; private set; } = string.Empty; + [Required] + public double Cost { get; set; } + [ForeignKey("ComponentId")] + public virtual List JewelComponents { get; set; } = new(); + public static Component? Create(ComponentBindingModel model) + { + if (model == null) + { + return null; + } + return new Component() + { + Id = model.Id, + ComponentName = model.ComponentName, + Cost = model.Cost + }; + } + public static Component Create(ComponentViewModel model) + { + return new Component + { + Id = model.Id, + ComponentName = model.ComponentName, + Cost = model.Cost + }; + } + public void Update(ComponentBindingModel model) + { + if (model == null) + { + return; + } + ComponentName = model.ComponentName; + Cost = model.Cost; + } + public ComponentViewModel GetViewModel => new() + { + Id = Id, + ComponentName = ComponentName, + Cost = Cost + }; + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Models/Jewel.cs b/JewelryStore/JewelryStoreDatabaseImplement/Models/Jewel.cs new file mode 100644 index 0000000..aa946f3 --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Models/Jewel.cs @@ -0,0 +1,97 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; +using JewelryStoreContracts.BindingModels; +using JewelryStoreContracts.ViewModels; +using JewerlyStoreDataModels.Models; + +namespace JewelryStoreDatabaseImplement.Models +{ + public class Jewel : IJewelModel + { + public int Id { get; set; } + [Required] + public string JewelName { get; set; } = string.Empty; + [Required] + public double Price { get; set; } + private Dictionary? _jewelComponents = null; + [NotMapped] + public Dictionary JewelComponents + { + get + { + if (_jewelComponents == null) + { + _jewelComponents = Components.ToDictionary(recJC => recJC.ComponentId, recJC => (recJC.Component as IComponentModel, recJC.Count)); + } + return _jewelComponents; + } + } + [ForeignKey("JewelId")] + public virtual List Components { get; set; } = new(); + [ForeignKey("JewelId")] + public virtual List Orders { get; set; } = new(); + + public static Jewel Create(JewelryStoreDatabase context, JewelBindingModel model) + { + return new Jewel() + { + Id = model.Id, + JewelName = model.JewelName, + Price = model.Price, + Components = model.JewelComponents.Select(x => new JewelComponent + { + Component = context.Components.First(y => y.Id == x.Key), + Count = x.Value.Item2 + }).ToList() + }; + } + + public void Update(JewelBindingModel model) + { + JewelName = model.JewelName; + Price = model.Price; + } + + public JewelViewModel GetViewModel => new() + { + Id = Id, + JewelName = JewelName, + Price = Price, + JewelComponents = JewelComponents + }; + + public void UpdateComponents(JewelryStoreDatabase context, JewelBindingModel model) + { + var jewelComponents = context.JewelComponents.Where(rec => rec.JewelId == model.Id).ToList(); + if (jewelComponents != null && jewelComponents.Count > 0) + { // удалили те, которых нет в модели + context.JewelComponents.RemoveRange(jewelComponents.Where(rec => !model.JewelComponents.ContainsKey(rec.ComponentId))); + context.SaveChanges(); + // обновили количество у существующих записей + foreach (var updateComponent in jewelComponents) + { + updateComponent.Count = model.JewelComponents[updateComponent.ComponentId].Item2; + model.JewelComponents.Remove(updateComponent.ComponentId); + } + context.SaveChanges(); + } + var jewel = context.Jewels.First(x => x.Id == Id); + foreach (var jc in model.JewelComponents) + { + context.JewelComponents.Add(new JewelComponent + { + Jewel = jewel, + Component = context.Components.First(x => x.Id == jc.Key), + Count = jc.Value.Item2 + }); + context.SaveChanges(); + } + _jewelComponents = null; + } + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Models/JewelComponent.cs b/JewelryStore/JewelryStoreDatabaseImplement/Models/JewelComponent.cs new file mode 100644 index 0000000..129697d --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Models/JewelComponent.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations; + +namespace JewelryStoreDatabaseImplement.Models +{ + public class JewelComponent + { + public int Id { get; set; } + [Required] + public int JewelId { get; set; } + [Required] + public int ComponentId { get; set; } + [Required] + public int Count { get; set; } + public virtual Component Component { get; set; } = new(); + public virtual Jewel Jewel { get; set; } = new(); + } +} diff --git a/JewelryStore/JewelryStoreDatabaseImplement/Models/Order.cs b/JewelryStore/JewelryStoreDatabaseImplement/Models/Order.cs new file mode 100644 index 0000000..b7013a2 --- /dev/null +++ b/JewelryStore/JewelryStoreDatabaseImplement/Models/Order.cs @@ -0,0 +1,68 @@ +using JewelryStoreContracts.BindingModels; +using JewelryStoreContracts.ViewModels; +using JewerlyStoreDataModels.Enums; +using JewerlyStoreDataModels.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace JewelryStoreDatabaseImplement.Models +{ + public class Order : IOrderModel + { + public int Id { get; private set; } + [Required] + public int JewelId { get; set; } + [Required] + public int Count { get; set; } + [Required] + public double Sum { get; set; } + [Required] + public OrderStatus Status { get; set; } + [Required] + public DateTime DateCreate { get; set; } + public DateTime? DateImplement { get; set; } + public Jewel Jewel { get; set; } + + public static Order? Create(OrderBindingModel? model) + { + if (model == null) + { + return null; + } + return new Order() + { + Id = model.Id, + JewelId = model.JewelId, + Count = model.Count, + Sum = model.Sum, + Status = model.Status, + DateCreate = model.DateCreate, + DateImplement = model.DateImplement + }; + } + public void Update(OrderBindingModel? model) + { + if (model == null) + { + return; + } + Status = model.Status; + if (model.DateImplement.HasValue) DateImplement = model.DateImplement; + } + public OrderViewModel GetViewModel => new() + { + Id = Id, + JewelId = JewelId, + Count = Count, + Sum = Sum, + Status = Status, + DateCreate = DateCreate, + DateImplement = DateImplement + }; + + } +} diff --git a/JewelryStore/JewelryStoreListImplement/JewelryStoreListImplement.csproj b/JewelryStore/JewelryStoreListImplement/JewelryStoreListImplement.csproj index eaba351..d08fa5a 100644 --- a/JewelryStore/JewelryStoreListImplement/JewelryStoreListImplement.csproj +++ b/JewelryStore/JewelryStoreListImplement/JewelryStoreListImplement.csproj @@ -6,6 +6,13 @@ enable + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/JewelryStore/JewerlyStoreDataModels/JewerlyStoreDataModels.csproj b/JewelryStore/JewerlyStoreDataModels/JewerlyStoreDataModels.csproj index 132c02c..a1003e1 100644 --- a/JewelryStore/JewerlyStoreDataModels/JewerlyStoreDataModels.csproj +++ b/JewelryStore/JewerlyStoreDataModels/JewerlyStoreDataModels.csproj @@ -6,4 +6,11 @@ enable + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/JewelryStore/JewerlyStoreFileImplement/JewerlyStoreFileImplement.csproj b/JewelryStore/JewerlyStoreFileImplement/JewerlyStoreFileImplement.csproj index eaba351..d08fa5a 100644 --- a/JewelryStore/JewerlyStoreFileImplement/JewerlyStoreFileImplement.csproj +++ b/JewelryStore/JewerlyStoreFileImplement/JewerlyStoreFileImplement.csproj @@ -6,6 +6,13 @@ enable + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + diff --git a/JewelryStore/JewerlyStoreView/JewerlyStoreView.csproj b/JewelryStore/JewerlyStoreView/JewerlyStoreView.csproj index 1b1bb14..13f79b7 100644 --- a/JewelryStore/JewerlyStoreView/JewerlyStoreView.csproj +++ b/JewelryStore/JewerlyStoreView/JewerlyStoreView.csproj @@ -9,6 +9,15 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -16,6 +25,7 @@ + diff --git a/JewelryStore/JewerlyStoreView/JewerlyStoreView.sln b/JewelryStore/JewerlyStoreView/JewerlyStoreView.sln new file mode 100644 index 0000000..097522b --- /dev/null +++ b/JewelryStore/JewerlyStoreView/JewerlyStoreView.sln @@ -0,0 +1,58 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewelryStoreBusinessLogic", "..\JewelryStoreBusinessLogic\JewelryStoreBusinessLogic.csproj", "{25D087CD-29D6-42C3-AB7D-0CF881DA7DAC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewelryStoreContracts", "..\JewelryStoreContracts\JewelryStoreContracts.csproj", "{F057F327-02A5-4407-996A-61BEA106E6BD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewelryStoreDatabaseImplement", "..\JewelryStoreDatabaseImplement\JewelryStoreDatabaseImplement.csproj", "{07B59EAD-064C-4CC2-8300-526EEAD7DF40}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewelryStoreListImplement", "..\JewelryStoreListImplement\JewelryStoreListImplement.csproj", "{8EE8B191-F9D3-4F61-B1BF-0F1200B26766}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewerlyStoreDataModels", "..\JewerlyStoreDataModels\JewerlyStoreDataModels.csproj", "{F8D0CC7E-1525-4837-B328-9FA606D6FF2D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewerlyStoreFileImplement", "..\JewerlyStoreFileImplement\JewerlyStoreFileImplement.csproj", "{AAFF546C-1A7B-435E-88E1-9EFFCB4DA7A1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JewerlyStoreView", "JewerlyStoreView.csproj", "{2A784D25-F667-471A-A320-0EF04F57953B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {25D087CD-29D6-42C3-AB7D-0CF881DA7DAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25D087CD-29D6-42C3-AB7D-0CF881DA7DAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25D087CD-29D6-42C3-AB7D-0CF881DA7DAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25D087CD-29D6-42C3-AB7D-0CF881DA7DAC}.Release|Any CPU.Build.0 = Release|Any CPU + {F057F327-02A5-4407-996A-61BEA106E6BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F057F327-02A5-4407-996A-61BEA106E6BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F057F327-02A5-4407-996A-61BEA106E6BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F057F327-02A5-4407-996A-61BEA106E6BD}.Release|Any CPU.Build.0 = Release|Any CPU + {07B59EAD-064C-4CC2-8300-526EEAD7DF40}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07B59EAD-064C-4CC2-8300-526EEAD7DF40}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07B59EAD-064C-4CC2-8300-526EEAD7DF40}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07B59EAD-064C-4CC2-8300-526EEAD7DF40}.Release|Any CPU.Build.0 = Release|Any CPU + {8EE8B191-F9D3-4F61-B1BF-0F1200B26766}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8EE8B191-F9D3-4F61-B1BF-0F1200B26766}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8EE8B191-F9D3-4F61-B1BF-0F1200B26766}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8EE8B191-F9D3-4F61-B1BF-0F1200B26766}.Release|Any CPU.Build.0 = Release|Any CPU + {F8D0CC7E-1525-4837-B328-9FA606D6FF2D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8D0CC7E-1525-4837-B328-9FA606D6FF2D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8D0CC7E-1525-4837-B328-9FA606D6FF2D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8D0CC7E-1525-4837-B328-9FA606D6FF2D}.Release|Any CPU.Build.0 = Release|Any CPU + {AAFF546C-1A7B-435E-88E1-9EFFCB4DA7A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AAFF546C-1A7B-435E-88E1-9EFFCB4DA7A1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AAFF546C-1A7B-435E-88E1-9EFFCB4DA7A1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AAFF546C-1A7B-435E-88E1-9EFFCB4DA7A1}.Release|Any CPU.Build.0 = Release|Any CPU + {2A784D25-F667-471A-A320-0EF04F57953B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A784D25-F667-471A-A320-0EF04F57953B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A784D25-F667-471A-A320-0EF04F57953B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A784D25-F667-471A-A320-0EF04F57953B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/JewelryStore/JewerlyStoreView/Program.cs b/JewelryStore/JewerlyStoreView/Program.cs index d44eff3..13a2767 100644 --- a/JewelryStore/JewerlyStoreView/Program.cs +++ b/JewelryStore/JewerlyStoreView/Program.cs @@ -1,6 +1,6 @@ using JewelryStoreContracts.BusinessLogicsContracts; using JewelryStoreContracts.StoragesContracts; -using JewerlyStoreFileImplement.Implements; +using JewelryStoreDatabaseImplement.Implements; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using NLog.Extensions.Logging;