diff --git a/BookShop/BookShop.sln b/BookShop/BookShop.sln
index cbefac8..cac5eff 100644
--- a/BookShop/BookShop.sln
+++ b/BookShop/BookShop.sln
@@ -3,9 +3,15 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.5.33530.505
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookShopView", "BookShopView\BookShopView.csproj", "{1455C2BC-5C22-4B93-8954-ACC01353BD24}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BookShopView", "BookShopView\BookShopView.csproj", "{1455C2BC-5C22-4B93-8954-ACC01353BD24}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookShopDataModels", "BookShopDataModels\BookShopDataModels.csproj", "{032BDFC0-6AAF-4A75-A9AE-B24C85A4679C}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BookShopDataModels", "BookShopDataModels\BookShopDataModels.csproj", "{032BDFC0-6AAF-4A75-A9AE-B24C85A4679C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookShopContracts", "BookShopContracts\BookShopContracts.csproj", "{0F724A0C-BAE5-4784-A7C5-FCCF7BE07EA5}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookShopBusinessLogic", "BookShopBusinessLogic\BookShopBusinessLogic.csproj", "{CA4B49FE-3671-4440-9E06-9B5F8D0CDB58}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BookShopDataBaseImplement", "BookShopDataBaseImplement\BookShopDataBaseImplement.csproj", "{EF559D7F-C94F-4F76-833E-44DF7FEDEDBD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -21,6 +27,18 @@ Global
{032BDFC0-6AAF-4A75-A9AE-B24C85A4679C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{032BDFC0-6AAF-4A75-A9AE-B24C85A4679C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{032BDFC0-6AAF-4A75-A9AE-B24C85A4679C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0F724A0C-BAE5-4784-A7C5-FCCF7BE07EA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0F724A0C-BAE5-4784-A7C5-FCCF7BE07EA5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0F724A0C-BAE5-4784-A7C5-FCCF7BE07EA5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0F724A0C-BAE5-4784-A7C5-FCCF7BE07EA5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CA4B49FE-3671-4440-9E06-9B5F8D0CDB58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CA4B49FE-3671-4440-9E06-9B5F8D0CDB58}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CA4B49FE-3671-4440-9E06-9B5F8D0CDB58}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CA4B49FE-3671-4440-9E06-9B5F8D0CDB58}.Release|Any CPU.Build.0 = Release|Any CPU
+ {EF559D7F-C94F-4F76-833E-44DF7FEDEDBD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {EF559D7F-C94F-4F76-833E-44DF7FEDEDBD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {EF559D7F-C94F-4F76-833E-44DF7FEDEDBD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {EF559D7F-C94F-4F76-833E-44DF7FEDEDBD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/BookShop/BookShopBusinessLogic/BookShopBusinessLogic.csproj b/BookShop/BookShopBusinessLogic/BookShopBusinessLogic.csproj
index 132c02c..40ad81a 100644
--- a/BookShop/BookShopBusinessLogic/BookShopBusinessLogic.csproj
+++ b/BookShop/BookShopBusinessLogic/BookShopBusinessLogic.csproj
@@ -6,4 +6,12 @@
enable
+
+
+
+
+
+
+
+
diff --git a/BookShop/BookShopContracts/BookShopContracts.csproj b/BookShop/BookShopContracts/BookShopContracts.csproj
index 132c02c..cec9677 100644
--- a/BookShop/BookShopContracts/BookShopContracts.csproj
+++ b/BookShop/BookShopContracts/BookShopContracts.csproj
@@ -6,4 +6,8 @@
enable
+
+
+
+
diff --git a/BookShop/BookShopDataBaseImplement/BookShopDataBaseImplement.csproj b/BookShop/BookShopDataBaseImplement/BookShopDataBaseImplement.csproj
new file mode 100644
index 0000000..f9d44cf
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/BookShopDataBaseImplement.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
diff --git a/BookShop/BookShopDataBaseImplement/BookShopDatabase.cs b/BookShop/BookShopDataBaseImplement/BookShopDatabase.cs
new file mode 100644
index 0000000..c8be76a
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/BookShopDatabase.cs
@@ -0,0 +1,23 @@
+using BookShopDataBaseImplement.Models;
+using Microsoft.EntityFrameworkCore;
+
+namespace BookShopDataBaseImplement
+{
+ public class BookShopDatabase : DbContext
+ {
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ if (optionsBuilder.IsConfigured == false)
+ {
+ optionsBuilder.UseNpgsql(@"Host=192.168.56.101;Port=5432;Database=SUBD_Lab2;Username=postgres;Password=postgres");
+ }
+ base.OnConfiguring(optionsBuilder);
+ }
+ public virtual DbSet Authors { set; get; }
+ public virtual DbSet Books { set; get; }
+ public virtual DbSet BookAuthors { set; get; }
+ public virtual DbSet Orders { set; get; }
+ public virtual DbSet Clients { set; get; }
+ public virtual DbSet Genres { set; get; }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Implements/AuthorStorage.cs b/BookShop/BookShopDataBaseImplement/Implements/AuthorStorage.cs
new file mode 100644
index 0000000..774b108
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Implements/AuthorStorage.cs
@@ -0,0 +1,76 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.SearchModels;
+using BookShopContracts.StoragesContracts;
+using BookShopContracts.ViewModels;
+using BookShopDataBaseImplement.Models;
+
+namespace BookShopDataBaseImplement.Implements
+{
+ public class AuthorStorage : IAuthorStorage
+ {
+ public AuthorViewModel? Delete(AuthorBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ var element = context.Authors.FirstOrDefault(rec => rec.Id == model.Id);
+ if (element != null)
+ {
+ context.Authors.Remove(element);
+ context.SaveChanges();
+ return element.GetViewModel;
+ }
+ return null;
+ }
+
+ public AuthorViewModel? GetElement(AuthorSearchModel model)
+ {
+ using var context = new BookShopDatabase();
+ if (model.Id.HasValue)
+ return context.Authors.FirstOrDefault(x => x.Id == model.Id)?.GetViewModel;
+ if (!string.IsNullOrEmpty(model.AuthorSurname))
+ return context.Authors.FirstOrDefault(x => x.AuthorSurname.Equals(model.AuthorSurname))?.GetViewModel;
+ return null;
+ }
+
+ public List GetFilteredList(AuthorSearchModel model)
+ {
+ if (string.IsNullOrEmpty(model.AuthorSurname))
+ {
+ return new();
+ }
+ using var context = new BookShopDatabase();
+ return context.Authors.Where(x => x.AuthorSurname.Contains(model.AuthorSurname)).Select(x => x.GetViewModel).ToList();
+ }
+
+ public List GetFullList()
+ {
+ using var context = new BookShopDatabase();
+ return context.Authors.Select(x => x.GetViewModel).ToList();
+ }
+
+ public AuthorViewModel? Insert(AuthorBindingModel model)
+ {
+ var newAuthor = Author.Create(model);
+ if (newAuthor == null)
+ {
+ return null;
+ }
+ using var context = new BookShopDatabase();
+ context.Authors.Add(newAuthor);
+ context.SaveChanges();
+ return newAuthor.GetViewModel;
+ }
+
+ public AuthorViewModel? Update(AuthorBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ var client = context.Authors.FirstOrDefault(x => x.Id == model.Id);
+ if (client == null)
+ {
+ return null;
+ }
+ client.Update(model);
+ context.SaveChanges();
+ return client.GetViewModel;
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Implements/BookStorage.cs b/BookShop/BookShopDataBaseImplement/Implements/BookStorage.cs
new file mode 100644
index 0000000..1196e07
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Implements/BookStorage.cs
@@ -0,0 +1,137 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.SearchModels;
+using BookShopContracts.StoragesContracts;
+using BookShopContracts.ViewModels;
+using BookShopDataBaseImplement.Models;
+using Microsoft.EntityFrameworkCore;
+using System.Diagnostics;
+
+namespace BookShopDataBaseImplement.Implements
+{
+ public class BookStorage : IBookStorage
+ {
+ public List GetFullList()
+ {
+ using var context = new BookShopDatabase();
+ return context.Books
+ .Include(x => x.Genre)
+ .Include(x => x.Authors)
+ .ThenInclude(x => x.Author)
+ .ToList()
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+ public List GetFilteredList(BookSearchModel model)
+ {
+ if (string.IsNullOrEmpty(model.BookName))
+ {
+ return new();
+ }
+ using var context = new BookShopDatabase();
+ return context.Books
+ .Include(x => x.Authors)
+ .ThenInclude(x => x.Author)
+ .Where(x => x.BookName.Contains(model.BookName))
+ .ToList()
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+ public BookViewModel? GetElement(BookSearchModel model)
+ {
+ if (string.IsNullOrEmpty(model.BookName) &&
+ !model.Id.HasValue)
+ {
+ return null;
+ }
+ using var context = new BookShopDatabase();
+ return context.Books
+ .Include(x => x.Authors)
+ .ThenInclude(x => x.Author)
+ .FirstOrDefault(x => (!string.IsNullOrEmpty(model.BookName) &&
+ x.BookName == model.BookName) ||
+ (model.Id.HasValue && x.Id ==
+ model.Id))
+ ?.GetViewModel;
+ }
+ public BookViewModel? Insert(BookBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ var newBook = Book.Create(context, model);
+ if (newBook == null)
+ {
+ return null;
+ }
+ context.Books.Add(newBook);
+ context.SaveChanges();
+ return newBook.GetViewModel;
+ }
+ public BookViewModel? Update(BookBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ using var transaction = context.Database.BeginTransaction();
+ try
+ {
+ var book = context.Books.FirstOrDefault(rec =>
+ rec.Id == model.Id);
+ if (book == null)
+ {
+ return null;
+ }
+ book.Update(model);
+ context.SaveChanges();
+ book.UpdateAuthors(context, model);
+ transaction.Commit();
+ return book.GetViewModel;
+ }
+ catch
+ {
+ transaction.Rollback();
+ throw;
+ }
+ }
+ public BookViewModel? Delete(BookBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ var element = context.Books
+ .Include(x => x.GenreId)
+ .Include(x => x.Authors)
+ .FirstOrDefault(rec => rec.Id == model.Id);
+ if (element != null)
+ {
+ context.Books.Remove(element);
+ context.SaveChanges();
+ return element.GetViewModel;
+ }
+ return null;
+ }
+ public string TestInsertList(int num)
+ {
+ throw new NotImplementedException();
+ }
+
+ public string TestReadList(int num)
+ {
+ var context = new BookShopDatabase();
+ Stopwatch stopwatch = new();
+
+ long[] res = new long[num];
+
+ for (int i = 0; i < num; i++)
+ {
+
+ stopwatch.Start();
+ List list = context.Books.Include(x => x.Genre).Include(x => x.Authors).ThenInclude(x => x.Author).ToList().Select(x => x.GetViewModel).ToList();
+ stopwatch.Stop();
+ res[i] = stopwatch.ElapsedMilliseconds;
+ }
+
+ long sum = 0;
+ for (int i = 0; i < num; i++)
+ {
+ sum += res[i];
+ }
+ int result = Convert.ToInt32(sum / num);
+ return result.ToString();
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Implements/ClientStorage.cs b/BookShop/BookShopDataBaseImplement/Implements/ClientStorage.cs
new file mode 100644
index 0000000..2ffb529
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Implements/ClientStorage.cs
@@ -0,0 +1,76 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.SearchModels;
+using BookShopContracts.StoragesContracts;
+using BookShopContracts.ViewModels;
+using BookShopDataBaseImplement.Models;
+
+namespace BookShopDataBaseImplement.Implements
+{
+ public class ClientStorage : IClientStorage
+ {
+ public ClientViewModel? Delete(ClientBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ var element = context.Clients.FirstOrDefault(rec => rec.Id == model.Id);
+ if (element != null)
+ {
+ context.Clients.Remove(element);
+ context.SaveChanges();
+ return element.GetViewModel;
+ }
+ return null;
+ }
+
+ public ClientViewModel? GetElement(ClientSearchModel model)
+ {
+ using var context = new BookShopDatabase();
+ if (model.Id.HasValue)
+ return context.Clients.FirstOrDefault(x => x.Id == model.Id)?.GetViewModel;
+ if (!string.IsNullOrEmpty(model.Email))
+ return context.Clients.FirstOrDefault(x => x.Email.Equals(model.Email))?.GetViewModel;
+ return null;
+ }
+
+ public List GetFilteredList(ClientSearchModel model)
+ {
+ if (string.IsNullOrEmpty(model.ClientSurname))
+ {
+ return new();
+ }
+ using var context = new BookShopDatabase();
+ return context.Clients.Where(x => x.ClientSurname.Contains(model.ClientSurname)).Select(x => x.GetViewModel).ToList();
+ }
+
+ public List GetFullList()
+ {
+ using var context = new BookShopDatabase();
+ return context.Clients.Select(x => x.GetViewModel).ToList();
+ }
+
+ public ClientViewModel? Insert(ClientBindingModel model)
+ {
+ var newClient = Client.Create(model);
+ if (newClient == null)
+ {
+ return null;
+ }
+ using var context = new BookShopDatabase();
+ context.Clients.Add(newClient);
+ context.SaveChanges();
+ return newClient.GetViewModel;
+ }
+
+ public ClientViewModel? Update(ClientBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ var client = context.Clients.FirstOrDefault(x => x.Id == model.Id);
+ if (client == null)
+ {
+ return null;
+ }
+ client.Update(model);
+ context.SaveChanges();
+ return client.GetViewModel;
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Implements/GenreStorage.cs b/BookShop/BookShopDataBaseImplement/Implements/GenreStorage.cs
new file mode 100644
index 0000000..1c7f7db
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Implements/GenreStorage.cs
@@ -0,0 +1,86 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.SearchModels;
+using BookShopContracts.StoragesContracts;
+using BookShopContracts.ViewModels;
+using BookShopDataBaseImplement.Models;
+using BookShopDataModels.Models;
+using System.ComponentModel;
+
+namespace BookShopDataBaseImplement.Implements
+{
+ public class GenreStorage : IGenreStorage
+ {
+ public List GetFullList()
+ {
+ using var context = new BookShopDatabase();
+ return context.Genres
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+ public List GetFilteredList(GenreSearchModel
+ model)
+ {
+ if (string.IsNullOrEmpty(model.GenreName))
+ {
+ return new();
+ }
+ using var context = new BookShopDatabase();
+ return context.Genres
+ .Where(x => x.GenreName.Contains(model.GenreName))
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+ public GenreViewModel? GetElement(GenreSearchModel model)
+ {
+ if (string.IsNullOrEmpty(model.GenreName) && !model.Id.HasValue)
+ {
+ return null;
+ }
+ using var context = new BookShopDatabase();
+ return context.Genres
+ .FirstOrDefault(x =>
+ (!string.IsNullOrEmpty(model.GenreName) && x.GenreName ==
+ model.GenreName) ||
+ (model.Id.HasValue && x.Id == model.Id))
+ ?.GetViewModel;
+ }
+ public GenreViewModel? Insert(GenreBindingModel model)
+ {
+ var newGenre = Genre.Create(model);
+ if (newGenre == null)
+ {
+ return null;
+ }
+ using var context = new BookShopDatabase();
+ context.Genres.Add(newGenre);
+ context.SaveChanges();
+ return newGenre.GetViewModel;
+ }
+ public GenreViewModel? Update(GenreBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ var genre = context.Genres.FirstOrDefault(x => x.Id ==
+ model.Id);
+ if (genre == null)
+ {
+ return null;
+ }
+ genre.Update(model);
+ context.SaveChanges();
+ return genre.GetViewModel;
+ }
+ public GenreViewModel? Delete(GenreBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+ var element = context.Genres.FirstOrDefault(rec => rec.Id ==
+ model.Id);
+ if (element != null)
+ {
+ context.Genres.Remove(element);
+ context.SaveChanges();
+ return element.GetViewModel;
+ }
+ return null;
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Implements/OrderStorage.cs b/BookShop/BookShopDataBaseImplement/Implements/OrderStorage.cs
new file mode 100644
index 0000000..99250be
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Implements/OrderStorage.cs
@@ -0,0 +1,103 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.SearchModels;
+using BookShopContracts.StoragesContracts;
+using BookShopContracts.ViewModels;
+using BookShopDataBaseImplement.Models;
+using Microsoft.EntityFrameworkCore;
+
+namespace BookShopDataBaseImplement.Implements
+{
+ public class OrderStorage : IOrderStorage
+ {
+ public OrderViewModel? Delete(OrderBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+
+ var element = context.Orders.Include(x => x.Book)
+ .Include(x => x.Client).FirstOrDefault(rec => rec.Id == model.Id);
+
+ if (element != null)
+ {
+ context.Orders.Remove(element);
+ context.SaveChanges();
+
+ return element.GetViewModel;
+ }
+
+ return null;
+ }
+
+ public OrderViewModel? GetElement(OrderSearchModel model)
+ {
+ if (!model.Id.HasValue)
+ {
+ return null;
+ }
+ using var context = new BookShopDatabase();
+ return context.Orders
+ .FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)
+ ?.GetViewModel;
+ }
+
+ public List GetFilteredList(OrderSearchModel model)
+ {
+ if (model is null)
+ {
+ return new();
+ }
+ using var context = new BookShopDatabase();
+ return context.Orders
+ .Where(x => x.ClientId == model.ClientId)
+ .ToList()
+ .Select(x => x.GetViewModel)
+ .ToList();
+ }
+
+ public List GetFullList()
+ {
+ using var context = new BookShopDatabase();
+
+ return context.Orders.Include(x => x.Book)
+ .Include(x => x.Client).Select(x => x.GetViewModel).ToList();
+ }
+
+ public OrderViewModel? Insert(OrderBindingModel model)
+ {
+ var newOrder = Order.Create(model);
+
+ if (newOrder == null)
+ {
+ return null;
+ }
+
+ using var context = new BookShopDatabase();
+
+ context.Orders.Add(newOrder);
+ context.SaveChanges();
+
+ return context.Orders
+ .Include(x => x.Book)
+ .Include(x => x.Client)
+ .FirstOrDefault(x => x.Id == newOrder.Id)
+ ?.GetViewModel;
+ }
+
+ public OrderViewModel? Update(OrderBindingModel model)
+ {
+ using var context = new BookShopDatabase();
+
+ var order = context.Orders.Include(x => x.Book)
+ .Include(x => x.Client).FirstOrDefault(x => x.Id == model.Id);
+
+ if (order == null)
+ {
+ return null;
+ }
+
+ order.Update(model);
+ context.SaveChanges();
+
+ return order.GetViewModel;
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Migrations/20230512083316_Initial.Designer.cs b/BookShop/BookShopDataBaseImplement/Migrations/20230512083316_Initial.Designer.cs
new file mode 100644
index 0000000..3bc2ca4
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Migrations/20230512083316_Initial.Designer.cs
@@ -0,0 +1,255 @@
+//
+using System;
+using BookShopDataBaseImplement;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace BookShopDataBaseImplement.Migrations
+{
+ [DbContext(typeof(BookShopDatabase))]
+ [Migration("20230512083316_Initial")]
+ partial class Initial
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.5")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Author", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AuthorName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("AuthorPatronymic")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("AuthorSurname")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Book", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BookName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Cost")
+ .HasColumnType("double precision");
+
+ b.Property("Count")
+ .HasColumnType("integer");
+
+ b.Property("GenreId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GenreId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.BookAuthor", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AuthorId")
+ .HasColumnType("integer");
+
+ b.Property("BookId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.HasIndex("BookId");
+
+ b.ToTable("BookAuthors");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Client", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ClientName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ClientPatronymic")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ClientSurname")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Clients");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Genre", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("GenreName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Genres");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Order", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BookId")
+ .HasColumnType("integer");
+
+ b.Property("ClientId")
+ .HasColumnType("integer");
+
+ b.Property("Count")
+ .HasColumnType("integer");
+
+ b.Property("DateCreate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Sum")
+ .HasColumnType("double precision");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BookId");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("Orders");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Book", b =>
+ {
+ b.HasOne("BookShopDataBaseImplement.Models.Genre", "Genre")
+ .WithMany("Books")
+ .HasForeignKey("GenreId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Genre");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.BookAuthor", b =>
+ {
+ b.HasOne("BookShopDataBaseImplement.Models.Author", "Author")
+ .WithMany("BookAuthors")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BookShopDataBaseImplement.Models.Book", "Book")
+ .WithMany("Authors")
+ .HasForeignKey("BookId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+
+ b.Navigation("Book");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Order", b =>
+ {
+ b.HasOne("BookShopDataBaseImplement.Models.Book", "Book")
+ .WithMany("Orders")
+ .HasForeignKey("BookId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BookShopDataBaseImplement.Models.Client", "Client")
+ .WithMany("Orders")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Book");
+
+ b.Navigation("Client");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Author", b =>
+ {
+ b.Navigation("BookAuthors");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Book", b =>
+ {
+ b.Navigation("Authors");
+
+ b.Navigation("Orders");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Client", b =>
+ {
+ b.Navigation("Orders");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Genre", b =>
+ {
+ b.Navigation("Books");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Migrations/20230512083316_Initial.cs b/BookShop/BookShopDataBaseImplement/Migrations/20230512083316_Initial.cs
new file mode 100644
index 0000000..14cec87
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Migrations/20230512083316_Initial.cs
@@ -0,0 +1,184 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace BookShopDataBaseImplement.Migrations
+{
+ ///
+ public partial class Initial : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Authors",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ AuthorSurname = table.Column(type: "text", nullable: false),
+ AuthorName = table.Column(type: "text", nullable: false),
+ AuthorPatronymic = table.Column(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Authors", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Clients",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ ClientSurname = table.Column(type: "text", nullable: false),
+ ClientName = table.Column(type: "text", nullable: false),
+ ClientPatronymic = table.Column(type: "text", nullable: false),
+ Email = table.Column(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Clients", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Genres",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ GenreName = table.Column(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Genres", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Books",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ BookName = table.Column(type: "text", nullable: false),
+ Count = table.Column(type: "integer", nullable: false),
+ Cost = table.Column(type: "double precision", nullable: false),
+ GenreId = table.Column(type: "integer", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Books", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Books_Genres_GenreId",
+ column: x => x.GenreId,
+ principalTable: "Genres",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "BookAuthors",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ BookId = table.Column(type: "integer", nullable: false),
+ AuthorId = table.Column(type: "integer", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_BookAuthors", x => x.Id);
+ table.ForeignKey(
+ name: "FK_BookAuthors_Authors_AuthorId",
+ column: x => x.AuthorId,
+ principalTable: "Authors",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_BookAuthors_Books_BookId",
+ column: x => x.BookId,
+ principalTable: "Books",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Orders",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ BookId = table.Column(type: "integer", nullable: false),
+ ClientId = table.Column(type: "integer", nullable: false),
+ Count = table.Column(type: "integer", nullable: false),
+ Sum = table.Column(type: "double precision", nullable: false),
+ DateCreate = table.Column(type: "timestamp with time zone", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Orders", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Orders_Books_BookId",
+ column: x => x.BookId,
+ principalTable: "Books",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_Orders_Clients_ClientId",
+ column: x => x.ClientId,
+ principalTable: "Clients",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_BookAuthors_AuthorId",
+ table: "BookAuthors",
+ column: "AuthorId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_BookAuthors_BookId",
+ table: "BookAuthors",
+ column: "BookId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Books_GenreId",
+ table: "Books",
+ column: "GenreId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Orders_BookId",
+ table: "Orders",
+ column: "BookId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Orders_ClientId",
+ table: "Orders",
+ column: "ClientId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "BookAuthors");
+
+ migrationBuilder.DropTable(
+ name: "Orders");
+
+ migrationBuilder.DropTable(
+ name: "Authors");
+
+ migrationBuilder.DropTable(
+ name: "Books");
+
+ migrationBuilder.DropTable(
+ name: "Clients");
+
+ migrationBuilder.DropTable(
+ name: "Genres");
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Migrations/BookShopDatabaseModelSnapshot.cs b/BookShop/BookShopDataBaseImplement/Migrations/BookShopDatabaseModelSnapshot.cs
new file mode 100644
index 0000000..6f65062
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Migrations/BookShopDatabaseModelSnapshot.cs
@@ -0,0 +1,252 @@
+//
+using System;
+using BookShopDataBaseImplement;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace BookShopDataBaseImplement.Migrations
+{
+ [DbContext(typeof(BookShopDatabase))]
+ partial class BookShopDatabaseModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.5")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Author", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AuthorName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("AuthorPatronymic")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("AuthorSurname")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Authors");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Book", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BookName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Cost")
+ .HasColumnType("double precision");
+
+ b.Property("Count")
+ .HasColumnType("integer");
+
+ b.Property("GenreId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GenreId");
+
+ b.ToTable("Books");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.BookAuthor", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AuthorId")
+ .HasColumnType("integer");
+
+ b.Property("BookId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AuthorId");
+
+ b.HasIndex("BookId");
+
+ b.ToTable("BookAuthors");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Client", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ClientName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ClientPatronymic")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ClientSurname")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Clients");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Genre", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("GenreName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Genres");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Order", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("BookId")
+ .HasColumnType("integer");
+
+ b.Property("ClientId")
+ .HasColumnType("integer");
+
+ b.Property("Count")
+ .HasColumnType("integer");
+
+ b.Property("DateCreate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Sum")
+ .HasColumnType("double precision");
+
+ b.HasKey("Id");
+
+ b.HasIndex("BookId");
+
+ b.HasIndex("ClientId");
+
+ b.ToTable("Orders");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Book", b =>
+ {
+ b.HasOne("BookShopDataBaseImplement.Models.Genre", "Genre")
+ .WithMany("Books")
+ .HasForeignKey("GenreId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Genre");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.BookAuthor", b =>
+ {
+ b.HasOne("BookShopDataBaseImplement.Models.Author", "Author")
+ .WithMany("BookAuthors")
+ .HasForeignKey("AuthorId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BookShopDataBaseImplement.Models.Book", "Book")
+ .WithMany("Authors")
+ .HasForeignKey("BookId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Author");
+
+ b.Navigation("Book");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Order", b =>
+ {
+ b.HasOne("BookShopDataBaseImplement.Models.Book", "Book")
+ .WithMany("Orders")
+ .HasForeignKey("BookId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("BookShopDataBaseImplement.Models.Client", "Client")
+ .WithMany("Orders")
+ .HasForeignKey("ClientId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Book");
+
+ b.Navigation("Client");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Author", b =>
+ {
+ b.Navigation("BookAuthors");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Book", b =>
+ {
+ b.Navigation("Authors");
+
+ b.Navigation("Orders");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Client", b =>
+ {
+ b.Navigation("Orders");
+ });
+
+ modelBuilder.Entity("BookShopDataBaseImplement.Models.Genre", b =>
+ {
+ b.Navigation("Books");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Models/Author.cs b/BookShop/BookShopDataBaseImplement/Models/Author.cs
new file mode 100644
index 0000000..e0913ec
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Models/Author.cs
@@ -0,0 +1,63 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.ViewModels;
+using BookShopDataModels.Models;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+
+namespace BookShopDataBaseImplement.Models
+{
+ public class Author : IAuthorModel
+ {
+ public int Id { get; private set; }
+ [Required]
+ public string AuthorSurname { get; set; } = string.Empty;
+ [Required]
+ public string AuthorName { get; set; } = string.Empty;
+ [Required]
+ public string AuthorPatronymic { get; set; } = string.Empty;
+
+ [ForeignKey("AuthorId")]
+ public virtual List BookAuthors { get; set; } = new();
+ public static Author? Create(AuthorBindingModel model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+ return new Author()
+ {
+ Id = model.Id,
+ AuthorSurname = model.AuthorSurname,
+ AuthorName = model.AuthorName,
+ AuthorPatronymic = model.AuthorPatronymic
+ };
+ }
+ public static Author Create(AuthorViewModel model)
+ {
+ return new Author
+ {
+ Id = model.Id,
+ AuthorSurname = model.AuthorSurname,
+ AuthorName = model.AuthorName,
+ AuthorPatronymic = model.AuthorPatronymic
+ };
+ }
+ public void Update(AuthorBindingModel model)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ AuthorSurname = model.AuthorSurname;
+ AuthorName = model.AuthorName;
+ AuthorPatronymic = model.AuthorPatronymic;
+ }
+ public AuthorViewModel GetViewModel => new()
+ {
+ Id = Id,
+ AuthorSurname = AuthorSurname,
+ AuthorName = AuthorName,
+ AuthorPatronymic = AuthorPatronymic
+ };
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Models/Book.cs b/BookShop/BookShopDataBaseImplement/Models/Book.cs
new file mode 100644
index 0000000..5e2df94
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Models/Book.cs
@@ -0,0 +1,108 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.ViewModels;
+using BookShopDataModels.Models;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics;
+
+namespace BookShopDataBaseImplement.Models
+{
+ public class Book : IBookModel
+ {
+ public int Id { get; private set; }
+ [Required]
+ public string BookName { get; set; } = string.Empty;
+ [Required]
+ public int Count { get; set; }
+ [Required]
+ public double Cost { get; set; }
+ [Required]
+ public int GenreId { get; set; }
+ public virtual Genre Genre { get; set; }
+ private Dictionary? _bookAuthors = null;
+ [NotMapped]
+ public Dictionary BookAuthors
+ {
+ get
+ {
+ if (_bookAuthors == null)
+ {
+ _bookAuthors = Authors.ToDictionary(recPC => recPC.AuthorId, recPC => recPC.Author as IAuthorModel);
+ }
+ return _bookAuthors;
+ }
+ }
+ [ForeignKey("BookId")]
+ public virtual List Authors { get; set; } = new();
+ [ForeignKey("BookId")]
+ public virtual List Orders { get; set; } = new();
+ public static Book Create(BookShopDatabase context, BookBindingModel model)
+ {
+ return new Book()
+ {
+ Id = model.Id,
+ BookName = model.BookName,
+ Cost = model.Cost,
+ Count = model.Count,
+ GenreId = model.GenreId,
+ Authors = model.BookAuthors.Select(x => new BookAuthor
+ {
+ Author = context.Authors.First(y => y.Id == x.Key)
+ }).ToList()
+ };
+ }
+ public void Update(BookBindingModel model)
+ {
+ BookName = model.BookName;
+ Cost = model.Cost;
+ Cost = model.Cost;
+ GenreId = model.GenreId;
+ }
+ public BookViewModel GetViewModel
+ {
+
+ get
+
+ {
+ using var context = new BookShopDatabase();
+ return new BookViewModel
+ {
+ Id = Id,
+ BookName = BookName,
+ Cost = Cost,
+ GenreId= GenreId,
+ GenreName = context.Genres.FirstOrDefault(x => x.Id == GenreId)?.GenreName ?? string.Empty,
+ BookAuthors = BookAuthors
+};
+ }
+}
+ public void UpdateAuthors(BookShopDatabase context, BookBindingModel model)
+ {
+ var bookAuthors = context.BookAuthors.Where(rec =>
+ rec.BookId == model.Id).ToList();
+ if (bookAuthors != null && bookAuthors.Count > 0)
+ { // удалили те, которых нет в модели
+ context.BookAuthors.RemoveRange(bookAuthors.Where(rec
+ => !model.BookAuthors.ContainsKey(rec.AuthorId)));
+ context.SaveChanges();
+ // обновили количество у существующих записей
+ foreach (var updateAuthor in bookAuthors)
+ {
+ model.BookAuthors.Remove(updateAuthor.AuthorId);
+ }
+ context.SaveChanges();
+ }
+ var book = context.Books.First(x => x.Id == Id);
+ foreach (var pc in model.BookAuthors)
+ {
+ context.BookAuthors.Add(new BookAuthor
+ {
+ Book = book,
+ Author = context.Authors.First(x => x.Id == pc.Key)
+ });
+ context.SaveChanges();
+ }
+ _bookAuthors = null;
+ }
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Models/BookAuthor.cs b/BookShop/BookShopDataBaseImplement/Models/BookAuthor.cs
new file mode 100644
index 0000000..20ee469
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Models/BookAuthor.cs
@@ -0,0 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel;
+
+namespace BookShopDataBaseImplement.Models
+{
+ public class BookAuthor
+ {
+ public int Id { get; set; }
+ [Required]
+ public int BookId { get; set; }
+ [Required]
+ public int AuthorId { get; set; }
+ public virtual Book Book { get; set; } = new();
+ public virtual Author Author { get; set; } = new();
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Models/Client.cs b/BookShop/BookShopDataBaseImplement/Models/Client.cs
new file mode 100644
index 0000000..e4bbd83
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Models/Client.cs
@@ -0,0 +1,69 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.ViewModels;
+using BookShopDataModels.Models;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+
+namespace BookShopDataBaseImplement.Models
+{
+ public class Client : IClientModel
+ {
+ public int Id { get; private set; }
+ [Required]
+ public string ClientSurname { get; set; } = string.Empty;
+ [Required]
+ public string ClientName { get; set; } = string.Empty;
+ [Required]
+ public string ClientPatronymic { get; set; } = string.Empty;
+ [Required]
+ public string Email { get; set; } = string.Empty;
+
+ [ForeignKey("ClientId")]
+ public virtual List Orders { get; set; } = new();
+ public static Client? Create(ClientBindingModel model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+ return new Client()
+ {
+ Id = model.Id,
+ ClientSurname = model.ClientSurname,
+ ClientName = model.ClientName,
+ ClientPatronymic = model.ClientPatronymic,
+ Email = model.Email
+ };
+ }
+ public static Client Create(ClientViewModel model)
+ {
+ return new Client
+ {
+ Id = model.Id,
+ ClientSurname = model.ClientSurname,
+ ClientName = model.ClientName,
+ ClientPatronymic = model.ClientPatronymic,
+ Email = model.Email
+ };
+ }
+ public void Update(ClientBindingModel model)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ ClientSurname = model.ClientSurname;
+ ClientName = model.ClientName;
+ ClientPatronymic = model.ClientPatronymic;
+ Email = model.Email;
+ }
+ public ClientViewModel GetViewModel => new()
+ {
+ Id = Id,
+ ClientSurname = ClientSurname,
+ ClientName = ClientName,
+ ClientPatronymic = ClientPatronymic,
+ Email = Email
+ };
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Models/Genre.cs b/BookShop/BookShopDataBaseImplement/Models/Genre.cs
new file mode 100644
index 0000000..fb318cd
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Models/Genre.cs
@@ -0,0 +1,51 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.ViewModels;
+using BookShopDataModels.Models;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.ComponentModel.DataAnnotations;
+
+namespace BookShopDataBaseImplement.Models
+{
+ public class Genre : IGenreModel
+ {
+ public int Id { get; private set; }
+ [Required]
+ public string GenreName { get; set; } = string.Empty;
+
+ [ForeignKey("GenreId")]
+ public virtual List Books { get; set; } = new();
+ public static Genre? Create(GenreBindingModel model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+ return new Genre()
+ {
+ Id = model.Id,
+ GenreName = model.GenreName
+ };
+ }
+ public static Genre Create(GenreViewModel model)
+ {
+ return new Genre
+ {
+ Id = model.Id,
+ GenreName = model.GenreName
+ };
+ }
+ public void Update(GenreBindingModel model)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ GenreName = model.GenreName;
+ }
+ public GenreViewModel GetViewModel => new()
+ {
+ Id = Id,
+ GenreName = GenreName
+ };
+ }
+}
diff --git a/BookShop/BookShopDataBaseImplement/Models/Order.cs b/BookShop/BookShopDataBaseImplement/Models/Order.cs
new file mode 100644
index 0000000..363e5b2
--- /dev/null
+++ b/BookShop/BookShopDataBaseImplement/Models/Order.cs
@@ -0,0 +1,79 @@
+using BookShopContracts.BindingModels;
+using BookShopContracts.ViewModels;
+using BookShopDataModels.Models;
+using System.ComponentModel.DataAnnotations;
+
+namespace BookShopDataBaseImplement.Models
+{
+ public class Order : IOrderModel
+ {
+ public int Id { get; private set; }
+
+ public int BookId { get; private set; }
+ [Required]
+ public int ClientId { get; set; }
+
+ [Required]
+ public int Count { get; private set; }
+
+ [Required]
+ public double Sum { get; private set; }
+
+ [Required]
+ public DateTime DateCreate { get; private set; } = DateTime.Now;
+
+ public virtual Book Book { get; set; }
+ public Client Client { get; set; }
+
+ public static Order? Create(OrderBindingModel? model)
+ {
+ if (model == null)
+ {
+ return null;
+ }
+
+ return new Order()
+ {
+ Id = model.Id,
+ ClientId = model.ClientId,
+ BookId = model.BookId,
+ Count = model.Count,
+ Sum = model.Sum,
+ DateCreate = model.DateCreate
+ };
+ }
+
+ public void Update(OrderBindingModel? model)
+ {
+ if (model == null)
+ {
+ return;
+ }
+ Id = model.Id;
+ ClientId = model.ClientId;
+ BookId = model.BookId;
+ Count = model.Count;
+ Sum = model.Sum;
+ DateCreate = model.DateCreate;
+ }
+
+ public OrderViewModel GetViewModel
+ {
+ get
+ {
+ using var context = new BookShopDatabase();
+ return new OrderViewModel
+ {
+ Id = Id,
+ ClientId = ClientId,
+ ClientSurname = context.Clients.FirstOrDefault(x => x.Id == ClientId)?.ClientSurname ?? string.Empty,
+ BookName = context.Books.FirstOrDefault(x => x.Id == BookId)?.BookName ?? string.Empty,
+ BookId = BookId,
+ Count = Count,
+ Sum = Sum,
+ DateCreate = DateCreate
+ };
+ }
+ }
+ }
+}
diff --git a/BookShop/BookShopView/BookShopView.csproj b/BookShop/BookShopView/BookShopView.csproj
index b57c89e..0162b34 100644
--- a/BookShop/BookShopView/BookShopView.csproj
+++ b/BookShop/BookShopView/BookShopView.csproj
@@ -8,4 +8,18 @@
enable
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file