Слои логики, котрактов и хранения

This commit is contained in:
ityurner02@mail.ru 2023-10-24 22:46:56 +04:00
parent ea707ec754
commit 21b0c10895
24 changed files with 792 additions and 2 deletions

View File

@ -7,6 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinForms", "WinForms\WinFor
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VisualCompLib", "VisualCompLib\VisualCompLib.csproj", "{FC1CFC63-5739-4519-B689-E8B614A9D106}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientsContracts", "ClientsContracts\ClientsContracts.csproj", "{849DCBC2-7B2D-43A5-87BD-CFE9BC4F0B6C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientBusinessLogic", "ClientBusinessLogic\ClientBusinessLogic.csproj", "{6A4A31E6-F956-4312-B63D-807ABF5CD63E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientsDatabaseImplement", "ClientsDatabaseImplement\ClientsDatabaseImplement.csproj", "{662252C6-5C66-43CD-8D94-5360E2761EB6}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -21,6 +27,18 @@ Global
{FC1CFC63-5739-4519-B689-E8B614A9D106}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC1CFC63-5739-4519-B689-E8B614A9D106}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC1CFC63-5739-4519-B689-E8B614A9D106}.Release|Any CPU.Build.0 = Release|Any CPU
{849DCBC2-7B2D-43A5-87BD-CFE9BC4F0B6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{849DCBC2-7B2D-43A5-87BD-CFE9BC4F0B6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{849DCBC2-7B2D-43A5-87BD-CFE9BC4F0B6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{849DCBC2-7B2D-43A5-87BD-CFE9BC4F0B6C}.Release|Any CPU.Build.0 = Release|Any CPU
{6A4A31E6-F956-4312-B63D-807ABF5CD63E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A4A31E6-F956-4312-B63D-807ABF5CD63E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A4A31E6-F956-4312-B63D-807ABF5CD63E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A4A31E6-F956-4312-B63D-807ABF5CD63E}.Release|Any CPU.Build.0 = Release|Any CPU
{662252C6-5C66-43CD-8D94-5360E2761EB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{662252C6-5C66-43CD-8D94-5360E2761EB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{662252C6-5C66-43CD-8D94-5360E2761EB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{662252C6-5C66-43CD-8D94-5360E2761EB6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -0,0 +1,62 @@
using ClientsContracts.BindingModels;
using ClientsContracts.BusinessLogicContracts;
using ClientsContracts.StorageContracts;
using ClientsContracts.ViewModels;
namespace ClientBusinessLogic.BusinessLogics
{
public class ClientLogic : IClientLogic
{
private readonly IClientStorage _clientStorage;
public ClientLogic(IClientStorage clientStorage)
{
_clientStorage = clientStorage;
}
public void CreateOrUpdate(ClientBindingModel model)
{
var element = _clientStorage.GetElement(
new ClientBindingModel
{
Reviews = model.Reviews,
Name = model.Name,
Status = model.Status,
Amount = model.Amount
});
if (element != null && element.Id != model.Id)
{
throw new Exception("Клиент с таким именем уже существует");
}
if (model.Id.HasValue)
{
_clientStorage.Update(model);
}
else
{
_clientStorage.Insert(model);
}
}
public void Delete(ClientBindingModel model)
{
var element = _clientStorage.GetElement(new ClientBindingModel { Id = model.Id });
if (element == null)
{
throw new Exception("Клиент не найден");
}
_clientStorage.Delete(model);
}
public List<ClientViewModel> Read(ClientBindingModel model)
{
if (model == null)
{
return _clientStorage.GetFullList();
}
if (model.Id.HasValue)
{
return new List<ClientViewModel> { _clientStorage.GetElement(model) };
}
return _clientStorage.GetFilteredList(model);
}
}
}

View File

@ -0,0 +1,60 @@
using ClientsContracts.BindingModels;
using ClientsContracts.BusinessLogicContracts;
using ClientsContracts.StorageContracts;
using ClientsContracts.ViewModels;
namespace ClientBusinessLogic.BusinessLogics
{
public class StatusLogic : IStatusLogic
{
private readonly IStatusStorage _statusStorage;
public StatusLogic(IStatusStorage statusStorage)
{
_statusStorage = statusStorage;
}
public void CreateOrUpdate(StatusBindingModel model)
{
var element = _statusStorage.GetElement(
new StatusBindingModel
{
Name = model.Name
});
if (element != null && element.Id != model.Id)
{
throw new Exception("Такой статус уже существует");
}
if (model.Id.HasValue)
{
_statusStorage.Update(model);
}
else
{
_statusStorage.Insert(model);
}
}
public void Delete(StatusBindingModel model)
{
var element = _statusStorage.GetElement(new StatusBindingModel { Id = model.Id });
if (element == null)
{
throw new Exception("Статус не найден");
}
_statusStorage.Delete(model);
}
public List<StatusViewModel> Read(StatusBindingModel model)
{
if (model == null)
{
return _statusStorage.GetFullList();
}
if (model.Id.HasValue)
{
return new List<StatusViewModel> { _statusStorage.GetElement(model) };
}
return _statusStorage.GetFilteredList(model);
}
}
}

View File

@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\ClientsContracts\ClientsContracts.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,15 @@
namespace ClientsContracts.BindingModels
{
public class ClientBindingModel
{
public int? Id { get; set; }
public string Name { get; set; }
public string Reviews { get; set; }
public string Status { get; set; }
public int? Amount { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace ClientsContracts.BindingModels
{
public class StatusBindingModel
{
public int? Id { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using ClientsContracts.BindingModels;
using ClientsContracts.ViewModels;
namespace ClientsContracts.BusinessLogicContracts
{
public interface IClientLogic
{
List<ClientViewModel> Read(ClientBindingModel model);
void CreateOrUpdate(ClientBindingModel model);
void Delete(ClientBindingModel model);
}
}

View File

@ -0,0 +1,12 @@
using ClientsContracts.BindingModels;
using ClientsContracts.ViewModels;
namespace ClientsContracts.BusinessLogicContracts
{
public interface IStatusLogic
{
List<StatusViewModel> Read(StatusBindingModel model);
void CreateOrUpdate(StatusBindingModel model);
void Delete(StatusBindingModel model);
}
}

View File

@ -0,0 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,16 @@
using ClientsContracts.BindingModels;
using ClientsContracts.ViewModels;
namespace ClientsContracts.StorageContracts
{
public interface IClientStorage
{
List<ClientViewModel> GetFullList();
List<ClientViewModel> GetFilteredList(ClientBindingModel model);
ClientViewModel GetElement(ClientBindingModel model);
void Insert(ClientBindingModel model);
void Update(ClientBindingModel model);
void Delete(ClientBindingModel model);
}
}

View File

@ -0,0 +1,16 @@
using ClientsContracts.BindingModels;
using ClientsContracts.ViewModels;
namespace ClientsContracts.StorageContracts
{
public interface IStatusStorage
{
List<StatusViewModel> GetFullList();
List<StatusViewModel> GetFilteredList(StatusBindingModel model);
StatusViewModel GetElement(StatusBindingModel model);
void Insert(StatusBindingModel model);
void Update(StatusBindingModel model);
void Delete(StatusBindingModel model);
}
}

View File

@ -0,0 +1,19 @@
using System.ComponentModel;
namespace ClientsContracts.ViewModels
{
public class ClientViewModel
{
public int? Id { get; set; }
[DisplayName("ФИО")]
public string Name { get; set; }
[DisplayName("Отзывы")]
public string Reviews { get; set; }
[DisplayName("Статус")]
public string Status { get; set; }
[DisplayName("Сумма покупок")]
public int? Amount { get; set; }
}
}

View File

@ -0,0 +1,9 @@
namespace ClientsContracts.ViewModels
{
public class StatusViewModel
{
public int? Id { get; set; }
public string Name { get; set; }
}
}

View File

@ -0,0 +1,19 @@
using Microsoft.EntityFrameworkCore;
using ClientsDatabaseImplement.Models;
namespace ClientsDatabaseImplement
{
public class ClientsDatabase : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (optionsBuilder.IsConfigured == false)
{
optionsBuilder.UseNpgsql(@"Host=localhost;Port=5432;Database=ClientsDatabase;Username=postgres;Password=186qazwsx");
}
base.OnConfiguring(optionsBuilder);
}
public virtual DbSet<Client> Clients { set; get; }
public virtual DbSet<Status> Statuses { set; get; }
}
}

View File

@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="7.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\ClientsContracts\ClientsContracts.csproj" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,120 @@
using ClientsContracts.StorageContracts;
using ClientsContracts.BindingModels;
using ClientsContracts.ViewModels;
using ClientsDatabaseImplement.Models;
namespace ClientsDatabaseImplement.Implements
{
public class ClientStorage : IClientStorage
{
public void Delete(ClientBindingModel model)
{
var context = new ClientsDatabase();
var client = context.Clients.FirstOrDefault(rec => rec.Id == model.Id);
if (client != null)
{
context.Clients.Remove(client);
context.SaveChanges();
}
else
{
throw new Exception("Клиент не найден");
}
}
public ClientViewModel GetElement(ClientBindingModel model)
{
if (model == null)
{
return null;
}
using var context = new ClientsDatabase();
var client = context.Clients
.ToList()
.FirstOrDefault(rec => rec.Id == model.Id);
return client != null ? CreateModel(client) : null;
}
public List<ClientViewModel> GetFilteredList(ClientBindingModel model)
{
var context = new ClientsDatabase();
return context.Clients
.Where(client => client.Name.Contains(model.Name) && client.Status.Contains(model.Status))
.ToList()
.Select(CreateModel)
.ToList();
}
public List<ClientViewModel> GetFullList()
{
using (var context = new ClientsDatabase())
{
return context.Clients
.ToList()
.Select(CreateModel)
.ToList();
}
}
public void Insert(ClientBindingModel model)
{
var context = new ClientsDatabase();
var transaction = context.Database.BeginTransaction();
try
{
context.Clients.Add(CreateModel(model, new Client()));
context.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
public void Update(ClientBindingModel model)
{
var context = new ClientsDatabase();
var transaction = context.Database.BeginTransaction();
try
{
var client = context.Clients.FirstOrDefault(rec => rec.Id == model.Id);
if (client == null)
{
throw new Exception("Клиент не найден");
}
CreateModel(model, client);
context.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
private static Client CreateModel(ClientBindingModel model, Client client)
{
client.Amount = model.Amount;
client.Name = model.Name;
client.Status = model.Status;
client.Reviews = model.Reviews;
return client;
}
private ClientViewModel CreateModel(Client client)
{
return new ClientViewModel
{
Id = client.Id,
Amount = client.Amount,
Name = client.Name,
Status = client.Status,
Reviews = client.Reviews
};
}
}
}

View File

@ -0,0 +1,115 @@
using ClientsContracts.StorageContracts;
using ClientsContracts.BindingModels;
using ClientsContracts.ViewModels;
using ClientsDatabaseImplement.Models;
namespace ClientsDatabaseImplement.Implements
{
public class StatusStorage : IStatusStorage
{
public void Delete(StatusBindingModel model)
{
var context = new ClientsDatabase();
var status = context.Statuses.FirstOrDefault(rec => rec.Id == model.Id);
if (status != null)
{
context.Statuses.Remove(status);
context.SaveChanges();
}
else
{
throw new Exception("Статус не найден");
}
}
public StatusViewModel GetElement(StatusBindingModel model)
{
if (model == null)
{
return null;
}
using var context = new ClientsDatabase();
var status = context.Statuses
.ToList()
.FirstOrDefault(rec => rec.Id == model.Id || rec.Name == model.Name);
return status != null ? CreateModel(status) : null;
}
public List<StatusViewModel> GetFilteredList(StatusBindingModel model)
{
if (model == null)
{
return null;
}
using var context = new ClientsDatabase();
return context.Statuses
.Where(rec => rec.Name.Contains(model.Name))
.Select(CreateModel)
.ToList();
}
public List<StatusViewModel> GetFullList()
{
using var context = new ClientsDatabase();
return context.Statuses
.Select(CreateModel)
.ToList();
}
public void Insert(StatusBindingModel model)
{
var context = new ClientsDatabase();
var transaction = context.Database.BeginTransaction();
try
{
context.Statuses.Add(CreateModel(model, new Status()));
context.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
public void Update(StatusBindingModel model)
{
var context = new ClientsDatabase();
var transaction = context.Database.BeginTransaction();
try
{
var status = context.Statuses.FirstOrDefault(rec => rec.Id == model.Id);
if (status == null)
{
throw new Exception("Статус не найден");
}
CreateModel(model, status);
context.SaveChanges();
transaction.Commit();
}
catch
{
transaction.Rollback();
throw;
}
}
private static Status CreateModel(StatusBindingModel model, Status status)
{
status.Name = model.Name;
return status;
}
private static StatusViewModel CreateModel(Status status)
{
return new StatusViewModel
{
Id = status.Id,
Name = status.Name
};
}
}
}

View File

@ -0,0 +1,75 @@
// <auto-generated />
using System;
using ClientsDatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace ClientsDatabaseImplement.Migrations
{
[DbContext(typeof(ClientsDatabase))]
[Migration("20231024184241_InitMigration")]
partial class InitMigration
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.11")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("ClientsDatabaseImplement.Models.Client", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int?>("Amount")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Reviews")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Clients");
});
modelBuilder.Entity("ClientsDatabaseImplement.Models.Status", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Statuses");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,54 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace ClientsDatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class InitMigration : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Clients",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Name = table.Column<string>(type: "text", nullable: false),
Reviews = table.Column<string>(type: "text", nullable: false),
Status = table.Column<string>(type: "text", nullable: false),
Amount = table.Column<int>(type: "integer", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Clients", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Statuses",
columns: table => new
{
Id = table.Column<int>(type: "integer", nullable: false)
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
Name = table.Column<string>(type: "text", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Statuses", x => x.Id);
});
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Clients");
migrationBuilder.DropTable(
name: "Statuses");
}
}
}

View File

@ -0,0 +1,72 @@
// <auto-generated />
using System;
using ClientsDatabaseImplement;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace ClientsDatabaseImplement.Migrations
{
[DbContext(typeof(ClientsDatabase))]
partial class ClientsDatabaseModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.11")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("ClientsDatabaseImplement.Models.Client", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<int?>("Amount")
.HasColumnType("integer");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Reviews")
.IsRequired()
.HasColumnType("text");
b.Property<string>("Status")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Clients");
});
modelBuilder.Entity("ClientsDatabaseImplement.Models.Status", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("integer");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("text");
b.HasKey("Id");
b.ToTable("Statuses");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,19 @@
using System.ComponentModel.DataAnnotations;
namespace ClientsDatabaseImplement.Models
{
public class Client
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Reviews { get; set; }
[Required]
public string Status { get; set; }
public int? Amount { get; set; }
}
}

View File

@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace ClientsDatabaseImplement.Models
{
public class Status
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
}

View File

@ -5,6 +5,7 @@
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>

View File

@ -9,11 +9,19 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Aspose.Words" Version="23.10.0" />
<PackageReference Include="ComponentsLibraryNet60" Version="1.0.0" />
<PackageReference Include="ControlsLibraryNet60" Version="1.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.11">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="UnvisableComponents" Version="1.0.0" />
<PackageReference Include="VisableComponents" Version="1.0.0" />
<PackageReference Include="VisualCompLib" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VisualCompLib\VisualCompLib.csproj" />
<ProjectReference Include="..\ClientsDatabaseImplement\ClientsDatabaseImplement.csproj" />
</ItemGroup>
</Project>