diff --git a/RouteDirectory/RouteDirectory.sln b/RouteDirectory/RouteDirectory.sln
index c988efb..42b171a 100644
--- a/RouteDirectory/RouteDirectory.sln
+++ b/RouteDirectory/RouteDirectory.sln
@@ -3,13 +3,15 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34723.18
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteDirectoryContracts", "RouteDirectoryContracts\RouteDirectoryContracts.csproj", "{2A635E80-4C36-404E-BD93-932BB9DDCC80}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RouteDirectoryContracts", "RouteDirectoryContracts\RouteDirectoryContracts.csproj", "{2A635E80-4C36-404E-BD93-932BB9DDCC80}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteDirectoryDatabaseImplement", "RouteDirectoryDatabaseImplement\RouteDirectoryDatabaseImplement.csproj", "{0EEFDAB4-25D2-452E-A6D7-9E24F83D72FB}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RouteDirectoryDatabaseImplement", "RouteDirectoryDatabaseImplement\RouteDirectoryDatabaseImplement.csproj", "{0EEFDAB4-25D2-452E-A6D7-9E24F83D72FB}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteDirectoryBusinessLogics", "RouteDirectoryBusinessLogics\RouteDirectoryBusinessLogics.csproj", "{1912B63E-8ECF-4C69-AD87-14CBCC537F53}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RouteDirectoryBusinessLogics", "RouteDirectoryBusinessLogics\RouteDirectoryBusinessLogics.csproj", "{1912B63E-8ECF-4C69-AD87-14CBCC537F53}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RouteDirectoryDataModels", "RouteDirectoryDataModels\RouteDirectoryDataModels\RouteDirectoryDataModels.csproj", "{FC55798A-CB32-4A98-9228-7370FCD6821D}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RouteDirectoryDataModels", "RouteDirectoryDataModels\RouteDirectoryDataModels\RouteDirectoryDataModels.csproj", "{FC55798A-CB32-4A98-9228-7370FCD6821D}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RouteDirectoryView", "RouteDirectoryForms\RouteDirectoryView.csproj", "{29E860E8-EEC1-43EF-9FA7-806AE3E71912}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -33,6 +35,10 @@ Global
{FC55798A-CB32-4A98-9228-7370FCD6821D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC55798A-CB32-4A98-9228-7370FCD6821D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC55798A-CB32-4A98-9228-7370FCD6821D}.Release|Any CPU.Build.0 = Release|Any CPU
+ {29E860E8-EEC1-43EF-9FA7-806AE3E71912}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {29E860E8-EEC1-43EF-9FA7-806AE3E71912}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {29E860E8-EEC1-43EF-9FA7-806AE3E71912}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {29E860E8-EEC1-43EF-9FA7-806AE3E71912}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/20240514183729_InitMigration.Designer.cs b/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/20240514183729_InitMigration.Designer.cs
new file mode 100644
index 0000000..419d549
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/20240514183729_InitMigration.Designer.cs
@@ -0,0 +1,201 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using RouteDirectoryDatabaseImplement;
+
+#nullable disable
+
+namespace RouteDirectoryDatabaseImplement.Migrations
+{
+ [DbContext(typeof(RouteDirectoryDatabase))]
+ [Migration("20240514183729_InitMigration")]
+ partial class InitMigration
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.17")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Route", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Fare")
+ .HasColumnType("int");
+
+ b.Property("RouteNumber")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("TransportId")
+ .HasColumnType("int");
+
+ b.Property("TransportTypeId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TransportTypeId");
+
+ b.ToTable("Routes");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.RouteStop", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Number")
+ .HasColumnType("int");
+
+ b.Property("RouteId")
+ .HasColumnType("int");
+
+ b.Property("StopId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RouteId");
+
+ b.HasIndex("StopId");
+
+ b.ToTable("RouteStops");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Schedule", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property("RouteId")
+ .HasColumnType("int");
+
+ b.Property("StartTime")
+ .HasColumnType("datetime2");
+
+ b.Property("TrafficInterval")
+ .HasColumnType("datetime2");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RouteId");
+
+ b.ToTable("Schedules");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Stop", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Number")
+ .HasColumnType("int");
+
+ b.Property("Street")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Stops");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.TransportType", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Capacity")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Type")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("TransportTypes");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Route", b =>
+ {
+ b.HasOne("RouteDirectoryDatabaseImplement.Models.TransportType", "TransportType")
+ .WithMany()
+ .HasForeignKey("TransportTypeId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("TransportType");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.RouteStop", b =>
+ {
+ b.HasOne("RouteDirectoryDatabaseImplement.Models.Route", "Route")
+ .WithMany("Stops")
+ .HasForeignKey("RouteId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("RouteDirectoryDatabaseImplement.Models.Stop", "Stop")
+ .WithMany()
+ .HasForeignKey("StopId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Route");
+
+ b.Navigation("Stop");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Schedule", b =>
+ {
+ b.HasOne("RouteDirectoryDatabaseImplement.Models.Route", "Route")
+ .WithMany()
+ .HasForeignKey("RouteId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Route");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Route", b =>
+ {
+ b.Navigation("Stops");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/20240514183729_InitMigration.cs b/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/20240514183729_InitMigration.cs
new file mode 100644
index 0000000..41efd80
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/20240514183729_InitMigration.cs
@@ -0,0 +1,154 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace RouteDirectoryDatabaseImplement.Migrations
+{
+ ///
+ public partial class InitMigration : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Stops",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ Name = table.Column(type: "nvarchar(max)", nullable: false),
+ Street = table.Column(type: "nvarchar(max)", nullable: false),
+ Number = table.Column(type: "int", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Stops", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "TransportTypes",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ Type = table.Column(type: "int", nullable: false),
+ Capacity = table.Column(type: "nvarchar(max)", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_TransportTypes", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Routes",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ RouteNumber = table.Column(type: "nvarchar(max)", nullable: false),
+ Fare = table.Column(type: "int", nullable: false),
+ TransportId = table.Column(type: "int", nullable: false),
+ TransportTypeId = table.Column(type: "int", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Routes", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Routes_TransportTypes_TransportTypeId",
+ column: x => x.TransportTypeId,
+ principalTable: "TransportTypes",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "RouteStops",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ RouteId = table.Column(type: "int", nullable: false),
+ StopId = table.Column(type: "int", nullable: false),
+ Number = table.Column(type: "int", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_RouteStops", x => x.Id);
+ table.ForeignKey(
+ name: "FK_RouteStops_Routes_RouteId",
+ column: x => x.RouteId,
+ principalTable: "Routes",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ table.ForeignKey(
+ name: "FK_RouteStops_Stops_StopId",
+ column: x => x.StopId,
+ principalTable: "Stops",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Schedules",
+ columns: table => new
+ {
+ Id = table.Column(type: "int", nullable: false)
+ .Annotation("SqlServer:Identity", "1, 1"),
+ StartTime = table.Column(type: "datetime2", nullable: false),
+ EndTime = table.Column(type: "datetime2", nullable: false),
+ TrafficInterval = table.Column(type: "datetime2", nullable: false),
+ RouteId = table.Column(type: "int", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Schedules", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Schedules_Routes_RouteId",
+ column: x => x.RouteId,
+ principalTable: "Routes",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Routes_TransportTypeId",
+ table: "Routes",
+ column: "TransportTypeId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_RouteStops_RouteId",
+ table: "RouteStops",
+ column: "RouteId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_RouteStops_StopId",
+ table: "RouteStops",
+ column: "StopId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Schedules_RouteId",
+ table: "Schedules",
+ column: "RouteId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "RouteStops");
+
+ migrationBuilder.DropTable(
+ name: "Schedules");
+
+ migrationBuilder.DropTable(
+ name: "Stops");
+
+ migrationBuilder.DropTable(
+ name: "Routes");
+
+ migrationBuilder.DropTable(
+ name: "TransportTypes");
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/RouteDirectoryDatabaseModelSnapshot.cs b/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/RouteDirectoryDatabaseModelSnapshot.cs
new file mode 100644
index 0000000..9873f1a
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryDatabaseImplement/Migrations/RouteDirectoryDatabaseModelSnapshot.cs
@@ -0,0 +1,198 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using RouteDirectoryDatabaseImplement;
+
+#nullable disable
+
+namespace RouteDirectoryDatabaseImplement.Migrations
+{
+ [DbContext(typeof(RouteDirectoryDatabase))]
+ partial class RouteDirectoryDatabaseModelSnapshot : ModelSnapshot
+ {
+ protected override void BuildModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "7.0.17")
+ .HasAnnotation("Relational:MaxIdentifierLength", 128);
+
+ SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Route", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Fare")
+ .HasColumnType("int");
+
+ b.Property("RouteNumber")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("TransportId")
+ .HasColumnType("int");
+
+ b.Property("TransportTypeId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TransportTypeId");
+
+ b.ToTable("Routes");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.RouteStop", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Number")
+ .HasColumnType("int");
+
+ b.Property("RouteId")
+ .HasColumnType("int");
+
+ b.Property("StopId")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RouteId");
+
+ b.HasIndex("StopId");
+
+ b.ToTable("RouteStops");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Schedule", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("EndTime")
+ .HasColumnType("datetime2");
+
+ b.Property("RouteId")
+ .HasColumnType("int");
+
+ b.Property("StartTime")
+ .HasColumnType("datetime2");
+
+ b.Property("TrafficInterval")
+ .HasColumnType("datetime2");
+
+ b.HasKey("Id");
+
+ b.HasIndex("RouteId");
+
+ b.ToTable("Schedules");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Stop", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Number")
+ .HasColumnType("int");
+
+ b.Property("Street")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.HasKey("Id");
+
+ b.ToTable("Stops");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.TransportType", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("int");
+
+ SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id"));
+
+ b.Property("Capacity")
+ .IsRequired()
+ .HasColumnType("nvarchar(max)");
+
+ b.Property("Type")
+ .HasColumnType("int");
+
+ b.HasKey("Id");
+
+ b.ToTable("TransportTypes");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Route", b =>
+ {
+ b.HasOne("RouteDirectoryDatabaseImplement.Models.TransportType", "TransportType")
+ .WithMany()
+ .HasForeignKey("TransportTypeId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("TransportType");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.RouteStop", b =>
+ {
+ b.HasOne("RouteDirectoryDatabaseImplement.Models.Route", "Route")
+ .WithMany("Stops")
+ .HasForeignKey("RouteId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("RouteDirectoryDatabaseImplement.Models.Stop", "Stop")
+ .WithMany()
+ .HasForeignKey("StopId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Route");
+
+ b.Navigation("Stop");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Schedule", b =>
+ {
+ b.HasOne("RouteDirectoryDatabaseImplement.Models.Route", "Route")
+ .WithMany()
+ .HasForeignKey("RouteId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Route");
+ });
+
+ modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Route", b =>
+ {
+ b.Navigation("Stops");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryDatabaseImplement/Models/Stop.cs b/RouteDirectory/RouteDirectoryDatabaseImplement/Models/Stop.cs
index cc606cf..44c2493 100644
--- a/RouteDirectory/RouteDirectoryDatabaseImplement/Models/Stop.cs
+++ b/RouteDirectory/RouteDirectoryDatabaseImplement/Models/Stop.cs
@@ -55,8 +55,6 @@ namespace RouteDirectoryDatabaseImplement.Models
{
Id = model.Id,
Name = model.Name,
- Street = model.Street,
- Number = model.Number
};
}
@@ -75,9 +73,7 @@ namespace RouteDirectoryDatabaseImplement.Models
return new Stop()
{
Id = model.Id,
- Name = model.Name,
- Street = model.Street,
- Number = model.Number
+ Name = model.Name
};
}
@@ -93,8 +89,6 @@ namespace RouteDirectoryDatabaseImplement.Models
}
Name = model.Name;
- Street = model.Street;
- Number = model.Number;
}
///
@@ -104,8 +98,6 @@ namespace RouteDirectoryDatabaseImplement.Models
{
Id = Id,
Name = Name,
- Street = Street,
- Number = Number
};
}
}
diff --git a/RouteDirectory/RouteDirectoryDatabaseImplement/RouteDirectoryDatabaseImplement.csproj b/RouteDirectory/RouteDirectoryDatabaseImplement/RouteDirectoryDatabaseImplement.csproj
index f0c1b83..9e93dc1 100644
--- a/RouteDirectory/RouteDirectoryDatabaseImplement/RouteDirectoryDatabaseImplement.csproj
+++ b/RouteDirectory/RouteDirectoryDatabaseImplement/RouteDirectoryDatabaseImplement.csproj
@@ -13,6 +13,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/RouteDirectory/RouteDirectoryDatabaseImplement/RouteGuideDatabase.cs b/RouteDirectory/RouteDirectoryDatabaseImplement/RouteGuideDatabase.cs
index cf5f8ee..ca4c696 100644
--- a/RouteDirectory/RouteDirectoryDatabaseImplement/RouteGuideDatabase.cs
+++ b/RouteDirectory/RouteDirectoryDatabaseImplement/RouteGuideDatabase.cs
@@ -8,13 +8,22 @@ using System.Threading.Tasks;
namespace RouteDirectoryDatabaseImplement
{
- public class RouteDirectoryDatabase : DbContext
+ public class RouteGuideDatabase : DbContext
{
+ ///
+ /// Параметры подключения к базе данных
+ ///
+ private string _dbConnectionString = "Host=192.168.56.102;Port=5432;Database=postgres;Username=postgres;Password=зщыепкуы";
+
+ ///
+ /// Подключение к базе данных
+ ///
+ ///
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (optionsBuilder.IsConfigured == false)
{
- optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-6QDRI0N\SQLEXPRESS;Initial Catalog=RouteDirectoryDatabase;Integrated Security=True;MultipleActiveResultSets=True;;TrustServerCertificate=True");
+ optionsBuilder.UseNpgsql(_dbConnectionString);
}
base.OnConfiguring(optionsBuilder);
}
diff --git a/RouteDirectory/RouteDirectoryForms/FormMain.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormMain.Designer.cs
new file mode 100644
index 0000000..b5426d2
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormMain.Designer.cs
@@ -0,0 +1,213 @@
+namespace RouteDirectoryView
+{
+ partial class FormMain
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ menuStrip1 = new MenuStrip();
+ справочникиToolStripMenuItem = new ToolStripMenuItem();
+ транспортToolStripMenuItem = new ToolStripMenuItem();
+ маршрутыToolStripMenuItem = new ToolStripMenuItem();
+ остановкиToolStripMenuItem = new ToolStripMenuItem();
+ тестыToolStripMenuItem = new ToolStripMenuItem();
+ транспортToolStripMenuItem1 = new ToolStripMenuItem();
+ маршрутыToolStripMenuItem1 = new ToolStripMenuItem();
+ остановкиToolStripMenuItem1 = new ToolStripMenuItem();
+ расписанияToolStripMenuItem = new ToolStripMenuItem();
+ dataGridView = new DataGridView();
+ buttonRefresh = new Button();
+ buttonDelete = new Button();
+ buttonUpdate = new Button();
+ buttonCreate = new Button();
+ menuStrip1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
+ SuspendLayout();
+ //
+ // menuStrip1
+ //
+ menuStrip1.ImageScalingSize = new Size(20, 20);
+ menuStrip1.Items.AddRange(new ToolStripItem[] { справочникиToolStripMenuItem, тестыToolStripMenuItem });
+ menuStrip1.Location = new Point(0, 0);
+ menuStrip1.Name = "menuStrip1";
+ menuStrip1.Size = new Size(1188, 28);
+ menuStrip1.TabIndex = 0;
+ menuStrip1.Text = "menuStrip1";
+ //
+ // справочникиToolStripMenuItem
+ //
+ справочникиToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { транспортToolStripMenuItem, маршрутыToolStripMenuItem, остановкиToolStripMenuItem });
+ справочникиToolStripMenuItem.Name = "справочникиToolStripMenuItem";
+ справочникиToolStripMenuItem.Size = new Size(117, 24);
+ справочникиToolStripMenuItem.Text = "Справочники";
+ //
+ // транспортToolStripMenuItem
+ //
+ транспортToolStripMenuItem.Name = "транспортToolStripMenuItem";
+ транспортToolStripMenuItem.Size = new Size(224, 26);
+ транспортToolStripMenuItem.Text = "Транспорт";
+ транспортToolStripMenuItem.Click += TransportToolStripMenuItem_Click;
+ //
+ // маршрутыToolStripMenuItem
+ //
+ маршрутыToolStripMenuItem.Name = "маршрутыToolStripMenuItem";
+ маршрутыToolStripMenuItem.Size = new Size(224, 26);
+ маршрутыToolStripMenuItem.Text = "Маршруты";
+ маршрутыToolStripMenuItem.Click += RoutesToolStripMenuItem_Click;
+ //
+ // остановкиToolStripMenuItem
+ //
+ остановкиToolStripMenuItem.Name = "остановкиToolStripMenuItem";
+ остановкиToolStripMenuItem.Size = new Size(224, 26);
+ остановкиToolStripMenuItem.Text = "Остановки";
+ остановкиToolStripMenuItem.Click += StopsToolStripMenuItem_Click;
+ //
+ // тестыToolStripMenuItem
+ //
+ тестыToolStripMenuItem.DropDownItems.AddRange(new ToolStripItem[] { транспортToolStripMenuItem1, маршрутыToolStripMenuItem1, остановкиToolStripMenuItem1, расписанияToolStripMenuItem });
+ тестыToolStripMenuItem.Name = "тестыToolStripMenuItem";
+ тестыToolStripMenuItem.Size = new Size(63, 24);
+ тестыToolStripMenuItem.Text = "Тесты";
+ //
+ // транспортToolStripMenuItem1
+ //
+ транспортToolStripMenuItem1.Name = "транспортToolStripMenuItem1";
+ транспортToolStripMenuItem1.Size = new Size(224, 26);
+ транспортToolStripMenuItem1.Text = "Транспорт";
+ транспортToolStripMenuItem1.Click += TransportTestsToolStripMenuItem_Click;
+ //
+ // маршрутыToolStripMenuItem1
+ //
+ маршрутыToolStripMenuItem1.Name = "маршрутыToolStripMenuItem1";
+ маршрутыToolStripMenuItem1.Size = new Size(224, 26);
+ маршрутыToolStripMenuItem1.Text = "Маршруты";
+ маршрутыToolStripMenuItem1.Click += RoutesTestsToolStripMenuItem_Click;
+ //
+ // остановкиToolStripMenuItem1
+ //
+ остановкиToolStripMenuItem1.Name = "остановкиToolStripMenuItem1";
+ остановкиToolStripMenuItem1.Size = new Size(224, 26);
+ остановкиToolStripMenuItem1.Text = "Остановки";
+ остановкиToolStripMenuItem1.Click += StopsTestsToolStripMenuItem_Click;
+ //
+ // расписанияToolStripMenuItem
+ //
+ расписанияToolStripMenuItem.Name = "расписанияToolStripMenuItem";
+ расписанияToolStripMenuItem.Size = new Size(224, 26);
+ расписанияToolStripMenuItem.Text = "Расписания";
+ расписанияToolStripMenuItem.Click += SchedulesTestsToolStripMenuItem_Click;
+ //
+ // dataGridView
+ //
+ dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ dataGridView.Location = new Point(0, 31);
+ dataGridView.Name = "dataGridView";
+ dataGridView.RowHeadersWidth = 51;
+ dataGridView.RowTemplate.Height = 29;
+ dataGridView.Size = new Size(1024, 419);
+ dataGridView.TabIndex = 1;
+ //
+ // buttonRefresh
+ //
+ buttonRefresh.Location = new Point(1063, 183);
+ buttonRefresh.Name = "buttonRefresh";
+ buttonRefresh.Size = new Size(94, 29);
+ buttonRefresh.TabIndex = 8;
+ buttonRefresh.Text = "Обновить";
+ buttonRefresh.UseVisualStyleBackColor = true;
+ buttonRefresh.Click += buttonRefresh_Click;
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(1063, 133);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(94, 29);
+ buttonDelete.TabIndex = 7;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ buttonDelete.Click += buttonDelete_Click;
+ //
+ // buttonUpdate
+ //
+ buttonUpdate.Location = new Point(1063, 82);
+ buttonUpdate.Name = "buttonUpdate";
+ buttonUpdate.Size = new Size(94, 29);
+ buttonUpdate.TabIndex = 6;
+ buttonUpdate.Text = "Изменить";
+ buttonUpdate.UseVisualStyleBackColor = true;
+ buttonUpdate.Click += buttonUpdate_Click;
+ //
+ // buttonCreate
+ //
+ buttonCreate.Location = new Point(1063, 31);
+ buttonCreate.Name = "buttonCreate";
+ buttonCreate.Size = new Size(94, 29);
+ buttonCreate.TabIndex = 5;
+ buttonCreate.Text = "Создать";
+ buttonCreate.UseVisualStyleBackColor = true;
+ buttonCreate.Click += buttonCreate_Click;
+ //
+ // FormMain
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(1188, 450);
+ Controls.Add(buttonRefresh);
+ Controls.Add(buttonDelete);
+ Controls.Add(buttonUpdate);
+ Controls.Add(buttonCreate);
+ Controls.Add(dataGridView);
+ Controls.Add(menuStrip1);
+ MainMenuStrip = menuStrip1;
+ Name = "FormMain";
+ Text = "Расписание";
+ Load += FormMain_Load;
+ menuStrip1.ResumeLayout(false);
+ menuStrip1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private MenuStrip menuStrip1;
+ private ToolStripMenuItem справочникиToolStripMenuItem;
+ private ToolStripMenuItem тестыToolStripMenuItem;
+ private DataGridView dataGridView;
+ private ToolStripMenuItem транспортToolStripMenuItem;
+ private ToolStripMenuItem маршрутыToolStripMenuItem;
+ private ToolStripMenuItem остановкиToolStripMenuItem;
+ private ToolStripMenuItem транспортToolStripMenuItem1;
+ private ToolStripMenuItem маршрутыToolStripMenuItem1;
+ private ToolStripMenuItem остановкиToolStripMenuItem1;
+ private ToolStripMenuItem расписанияToolStripMenuItem;
+ private Button buttonRefresh;
+ private Button buttonDelete;
+ private Button buttonUpdate;
+ private Button buttonCreate;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormMain.cs b/RouteDirectory/RouteDirectoryForms/FormMain.cs
new file mode 100644
index 0000000..4568e2f
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormMain.cs
@@ -0,0 +1,252 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using RouteDirectoryForms;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ public partial class FormMain : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика для расписаний
+ ///
+ private readonly IScheduleLogic _schedulelogic;
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ ///
+ public FormMain(ILogger logger, IScheduleLogic scheduleLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _schedulelogic = scheduleLogic;
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ ///
+ ///
+ private void FormMain_Load(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Форма для вывода списка транспорта
+ ///
+ ///
+ ///
+ private void TransportToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormTransports));
+ if (service is FormTransports form)
+ {
+ form.ShowDialog();
+ }
+ }
+
+ ///
+ /// Форма для вывода списка маршрутов
+ ///
+ ///
+ ///
+ private void RoutesToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormRoutes));
+ if (service is FormRoutes form)
+ {
+ form.ShowDialog();
+ }
+ }
+
+ ///
+ /// Форма для вывода списка остановок
+ ///
+ ///
+ ///
+ private void StopsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormStops));
+ if (service is FormStops form)
+ {
+ form.ShowDialog();
+ }
+ }
+
+ ///
+ /// Форма для тестов сущности "Транспорт"
+ ///
+ ///
+ ///
+ private void TransportTestsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormTransportTests));
+ if (service is FormTransportTests form)
+ {
+ form.ShowDialog();
+ }
+ }
+
+ ///
+ /// Форма для тестов сущности "Маршрут"
+ ///
+ ///
+ ///
+ private void RoutesTestsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormRoutesTests));
+ if (service is FormRoutesTests form)
+ {
+ form.ShowDialog();
+ }
+ }
+
+ ///
+ /// Форма для тестов сущности "Остановка"
+ ///
+ ///
+ ///
+ private void StopsTestsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormStopsTests));
+ if (service is FormStopsTests form)
+ {
+ form.ShowDialog();
+ }
+ }
+
+ ///
+ /// Форма для тестов сущности "Расписание"
+ ///
+ ///
+ ///
+ private void SchedulesTestsToolStripMenuItem_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormSchedulesTests));
+ if (service is FormSchedulesTests form)
+ {
+ form.ShowDialog();
+ }
+ }
+
+ ///
+ /// Кнопка "Создать"
+ ///
+ ///
+ ///
+ private void buttonCreate_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormSchedule));
+ if (service is FormSchedule form)
+ {
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ LoadData();
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Изменить"
+ ///
+ ///
+ ///
+ private void buttonUpdate_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormSchedule));
+ if (service is FormSchedule form)
+ {
+ form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ LoadData();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Удалить"
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
+ {
+ int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
+ _logger.LogInformation("Удаление сущности 'Расписание'");
+
+ try
+ {
+ if (!_schedulelogic.Delete(new ScheduleBindingModel { Id = id }))
+ {
+ throw new Exception("Ошибка при удалении сущности 'Расписание'. Дополнительная информация в логах.");
+ }
+ LoadData();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка удаления сущности 'Расписание'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Обновить"
+ ///
+ ///
+ ///
+ private void buttonRefresh_Click(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ private void LoadData()
+ {
+ try
+ {
+ var list = _schedulelogic.ReadList(null);
+ if (list != null)
+ {
+ dataGridView.DataSource = list;
+ dataGridView.Columns["Id"].Visible = false;
+ dataGridView.Columns["RouteId"].Visible = false;
+ dataGridView.Columns["RouteNumber"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
+ }
+ _logger.LogInformation("Загрузка списка расписаний");
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка загрузки списка расписаний");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormMain.resx b/RouteDirectory/RouteDirectoryForms/FormMain.resx
new file mode 100644
index 0000000..a0623c8
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormMain.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoute.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormRoute.Designer.cs
new file mode 100644
index 0000000..a704719
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoute.Designer.cs
@@ -0,0 +1,227 @@
+namespace RouteDirectoryView
+{
+ partial class FormRoute
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ textBoxName = new TextBox();
+ comboBoxTransport = new ComboBox();
+ labelName = new Label();
+ labelTransport = new Label();
+ groupBox = new GroupBox();
+ dataGridView = new DataGridView();
+ ColumnId = new DataGridViewTextBoxColumn();
+ ColumnName = new DataGridViewTextBoxColumn();
+ ColumNumber = new DataGridViewTextBoxColumn();
+ buttonCreate = new Button();
+ buttonUpdate = new Button();
+ buttonDelete = new Button();
+ buttonRefresh = new Button();
+ buttonSave = new Button();
+ buttonCancel = new Button();
+ groupBox.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
+ SuspendLayout();
+ //
+ // textBoxName
+ //
+ textBoxName.Location = new Point(98, 13);
+ textBoxName.Name = "textBoxName";
+ textBoxName.Size = new Size(224, 27);
+ textBoxName.TabIndex = 0;
+ //
+ // comboBoxTransport
+ //
+ comboBoxTransport.FormattingEnabled = true;
+ comboBoxTransport.Location = new Point(510, 12);
+ comboBoxTransport.Name = "comboBoxTransport";
+ comboBoxTransport.Size = new Size(224, 28);
+ comboBoxTransport.TabIndex = 1;
+ //
+ // labelName
+ //
+ labelName.AutoSize = true;
+ labelName.Location = new Point(12, 15);
+ labelName.Name = "labelName";
+ labelName.Size = new Size(80, 20);
+ labelName.TabIndex = 2;
+ labelName.Text = "Название:";
+ //
+ // labelTransport
+ //
+ labelTransport.AutoSize = true;
+ labelTransport.Location = new Point(421, 15);
+ labelTransport.Name = "labelTransport";
+ labelTransport.Size = new Size(83, 20);
+ labelTransport.TabIndex = 3;
+ labelTransport.Text = "Транспорт";
+ //
+ // groupBox
+ //
+ groupBox.Controls.Add(buttonRefresh);
+ groupBox.Controls.Add(buttonDelete);
+ groupBox.Controls.Add(buttonUpdate);
+ groupBox.Controls.Add(buttonCreate);
+ groupBox.Controls.Add(dataGridView);
+ groupBox.Location = new Point(12, 46);
+ groupBox.Name = "groupBox";
+ groupBox.Size = new Size(776, 393);
+ groupBox.TabIndex = 4;
+ groupBox.TabStop = false;
+ groupBox.Text = "Остановки";
+ //
+ // dataGridView
+ //
+ dataGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
+ dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ dataGridView.Columns.AddRange(new DataGridViewColumn[] { ColumnId, ColumnName, ColumNumber });
+ dataGridView.Location = new Point(0, 26);
+ dataGridView.Name = "dataGridView";
+ dataGridView.RowHeadersWidth = 51;
+ dataGridView.RowTemplate.Height = 29;
+ dataGridView.Size = new Size(665, 354);
+ dataGridView.TabIndex = 0;
+ //
+ // ColumnId
+ //
+ ColumnId.HeaderText = "Column1";
+ ColumnId.MinimumWidth = 6;
+ ColumnId.Name = "ColumnId";
+ ColumnId.Visible = false;
+ //
+ // ColumnName
+ //
+ ColumnName.HeaderText = "Остановка";
+ ColumnName.MinimumWidth = 6;
+ ColumnName.Name = "ColumnName";
+ //
+ // ColumNumber
+ //
+ ColumNumber.HeaderText = "Номер остановки";
+ ColumNumber.MinimumWidth = 6;
+ ColumNumber.Name = "ColumNumber";
+ //
+ // buttonCreate
+ //
+ buttonCreate.Location = new Point(671, 26);
+ buttonCreate.Name = "buttonCreate";
+ buttonCreate.Size = new Size(94, 29);
+ buttonCreate.TabIndex = 1;
+ buttonCreate.Text = "Создать";
+ buttonCreate.UseVisualStyleBackColor = true;
+ buttonCreate.Click += buttonCreate_Click;
+ //
+ // buttonUpdate
+ //
+ buttonUpdate.Location = new Point(671, 73);
+ buttonUpdate.Name = "buttonUpdate";
+ buttonUpdate.Size = new Size(94, 29);
+ buttonUpdate.TabIndex = 2;
+ buttonUpdate.Text = "Изменить";
+ buttonUpdate.UseVisualStyleBackColor = true;
+ buttonUpdate.Click += buttonUpdate_Click;
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(671, 119);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(94, 29);
+ buttonDelete.TabIndex = 3;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ buttonDelete.Click += buttonDelete_Click;
+ //
+ // buttonRefresh
+ //
+ buttonRefresh.Location = new Point(671, 167);
+ buttonRefresh.Name = "buttonRefresh";
+ buttonRefresh.Size = new Size(94, 29);
+ buttonRefresh.TabIndex = 4;
+ buttonRefresh.Text = "Обновить";
+ buttonRefresh.UseVisualStyleBackColor = true;
+ buttonRefresh.Click += buttonRefresh_Click;
+ //
+ // buttonSave
+ //
+ buttonSave.Location = new Point(583, 445);
+ buttonSave.Name = "buttonSave";
+ buttonSave.Size = new Size(94, 29);
+ buttonSave.TabIndex = 5;
+ buttonSave.Text = "Сохранить";
+ buttonSave.UseVisualStyleBackColor = true;
+ buttonSave.Click += buttonSave_Click;
+ //
+ // buttonCancel
+ //
+ buttonCancel.Location = new Point(694, 445);
+ buttonCancel.Name = "buttonCancel";
+ buttonCancel.Size = new Size(94, 29);
+ buttonCancel.TabIndex = 6;
+ buttonCancel.Text = "Отмена";
+ buttonCancel.UseVisualStyleBackColor = true;
+ buttonCancel.Click += buttonCancel_Click;
+ //
+ // FormRoute
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(800, 491);
+ Controls.Add(buttonSave);
+ Controls.Add(buttonCancel);
+ Controls.Add(groupBox);
+ Controls.Add(labelTransport);
+ Controls.Add(labelName);
+ Controls.Add(comboBoxTransport);
+ Controls.Add(textBoxName);
+ Name = "FormRoute";
+ Text = "Маршрут";
+ Load += FormRoute_Load;
+ groupBox.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private TextBox textBoxName;
+ private ComboBox comboBoxTransport;
+ private Label labelName;
+ private Label labelTransport;
+ private GroupBox groupBox;
+ private DataGridView dataGridView;
+ private DataGridViewTextBoxColumn ColumnId;
+ private DataGridViewTextBoxColumn ColumnName;
+ private DataGridViewTextBoxColumn ColumNumber;
+ private Button buttonRefresh;
+ private Button buttonDelete;
+ private Button buttonUpdate;
+ private Button buttonCreate;
+ private Button buttonSave;
+ private Button buttonCancel;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoute.cs b/RouteDirectory/RouteDirectoryForms/FormRoute.cs
new file mode 100644
index 0000000..311ecd1
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoute.cs
@@ -0,0 +1,304 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using RouteDirectoryContracts.SearchModels;
+using RouteDirectoryDataModels.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма для создания/редактирования маршрутов
+ ///
+ public partial class FormRoute : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика маршрутов
+ ///
+ private readonly IRouteLogic _routeLogic;
+
+ ///
+ /// Бизнес-логика транспорта
+ ///
+ private readonly ITransportTypeLogic _transportLogic;
+
+ ///
+ /// Идентификатор
+ ///
+ private int? _id;
+
+ ///
+ /// Идентификатор
+ ///
+ public int Id { set { _id = value; } }
+
+ ///
+ /// Список остановок в маршруте
+ ///
+ private Dictionary _routeStops;
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ ///
+ public FormRoute(ILogger logger, IRouteLogic routeLogic, ITransportTypeLogic transportLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _routeLogic = routeLogic;
+ _transportLogic = transportLogic;
+ _routeStops = new Dictionary();
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ ///
+ ///
+ private void FormRoute_Load(object sender, EventArgs e)
+ {
+ try
+ {
+ // Загрузка маршрутов для ComboBoxTransport
+ _logger.LogInformation("Загрузка списка транспорта");
+ var list = _transportLogic.ReadList(null);
+ if (list != null)
+ {
+ comboBoxTransport.ValueMember = "Id";
+ comboBoxTransport.DataSource = list;
+ comboBoxTransport.SelectedItem = null;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка загрузки списка транспорта");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+
+ if (!_id.HasValue)
+ {
+ return;
+ }
+
+ try
+ {
+ _logger.LogInformation("Получение сущности 'Маршрут'");
+ var view = _routeLogic.ReadElement(new RouteSearchModel
+ {
+ Id = _id.Value
+ });
+ if (view != null)
+ {
+ textBoxName.Text = view.RouteNumber;
+ comboBoxTransport.SelectedValue = view.TransportId;
+ _routeStops = view.RouteStops ?? new Dictionary();
+ LoadData();
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка получения сущности 'Маршрут'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Добавить"
+ ///
+ ///
+ ///
+ private void buttonCreate_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormRouteStop));
+ if (service is FormRouteStop form)
+ {
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ if (form.StopModel == null)
+ {
+ return;
+ }
+
+ _logger.LogInformation("Добавление остановки.{Id}: {StopName} в маршрут на позицию {Number}", form.Id, form.StopModel.Name, form.Number);
+ if (_routeStops.ContainsKey(form.Id))
+ {
+ _routeStops[form.Id] = (form.StopModel, form.Number);
+ }
+ else
+ {
+ _routeStops.Add(form.Id, (form.StopModel, form.Number));
+ }
+ LoadData();
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Изменить"
+ ///
+ ///
+ ///
+ private void buttonUpdate_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormRouteStop));
+ if (service is FormRouteStop form)
+ {
+ int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value);
+ form.Id = id;
+ form.Number = _routeStops[id].Item2;
+
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ if (form.StopModel == null)
+ {
+ return;
+ }
+
+ _logger.LogInformation("Изменение остановки.{Id}: {StopName} в маршруте на позиции {Number}", form.Id, form.StopModel.Name, form.Number);
+ _routeStops[form.Id] = (form.StopModel, form.Number);
+ LoadData();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Удалить"
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
+ {
+ try
+ {
+ _logger.LogInformation("Удаление остановки.{Id}: {StopName} с позиции в маршруте {Number}", dataGridView.SelectedRows[0].Cells[0].Value, dataGridView.SelectedRows[0].Cells[1].Value, dataGridView.SelectedRows[0].Cells[2].Value);
+ _routeStops.Remove(Convert.ToInt32(dataGridView.SelectedRows[0].Cells[0].Value));
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка удаления остановки.{Id}: {StopName} с позиции в маршруте {Number}", dataGridView.SelectedRows[0].Cells[0].Value, dataGridView.SelectedRows[0].Cells[1].Value, dataGridView.SelectedRows[0].Cells[2].Value);
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ LoadData();
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Обновить"
+ ///
+ ///
+ ///
+ private void buttonRefresh_Click(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Кнопка "Сохранить"
+ ///
+ ///
+ ///
+ private void buttonSave_Click(object sender, EventArgs e)
+ {
+ if (string.IsNullOrEmpty(textBoxName.Text))
+ {
+ MessageBox.Show("Заполните название маршрута", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ if (comboBoxTransport.SelectedValue == null)
+ {
+ MessageBox.Show("Выберите транспорт", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ _logger.LogInformation("Сохранение сущности 'Маршрут'");
+ try
+ {
+ var model = new RouteBindingModel
+ {
+ Id = _id ?? 0,
+ RouteNumber = textBoxName.Text,
+ TransportId = Convert.ToInt32(comboBoxTransport.SelectedValue),
+ RouteStops = _routeStops
+ };
+
+ var operationResult = _id.HasValue ? _routeLogic.Update(model) : _routeLogic.Create(model);
+ if (!operationResult)
+ {
+ throw new Exception("Ошибка при сохранении сущности 'Маршрут'. Дополнительная информация в логах.");
+ }
+
+ MessageBox.Show("Сохранение сущности 'Маршрут' прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка сохранения сущности 'Маршрут'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Отмена"
+ ///
+ ///
+ ///
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ private void LoadData()
+ {
+ _logger.LogInformation("Загрузка списка остановок в маршруте");
+ try
+ {
+ if (_routeStops != null)
+ {
+ dataGridView.Rows.Clear();
+ foreach (var rs in _routeStops)
+ {
+ dataGridView.Rows.Add(new object[]
+ {
+ rs.Key,
+ rs.Value.Item1.Name,
+ rs.Value.Item2
+ });
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка загрузки списка остановок в маршруте");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoute.resx b/RouteDirectory/RouteDirectoryForms/FormRoute.resx
new file mode 100644
index 0000000..5dd2428
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoute.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ True
+
+
+ True
+
+
+ True
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormRouteStop.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormRouteStop.Designer.cs
new file mode 100644
index 0000000..f1b0eb6
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRouteStop.Designer.cs
@@ -0,0 +1,118 @@
+namespace RouteDirectoryView
+{
+ partial class FormRouteStop
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ labelStop = new Label();
+ labelNumber = new Label();
+ comboBoxStop = new ComboBox();
+ textBoxNumber = new TextBox();
+ buttonSave = new Button();
+ buttonCancel = new Button();
+ SuspendLayout();
+ //
+ // labelStop
+ //
+ labelStop.AutoSize = true;
+ labelStop.Location = new Point(12, 25);
+ labelStop.Name = "labelStop";
+ labelStop.Size = new Size(85, 20);
+ labelStop.TabIndex = 0;
+ labelStop.Text = "Остановка:";
+ //
+ // labelNumber
+ //
+ labelNumber.AutoSize = true;
+ labelNumber.Location = new Point(12, 79);
+ labelNumber.Name = "labelNumber";
+ labelNumber.Size = new Size(60, 20);
+ labelNumber.TabIndex = 1;
+ labelNumber.Text = "Номер:";
+ //
+ // comboBoxStop
+ //
+ comboBoxStop.FormattingEnabled = true;
+ comboBoxStop.Location = new Point(114, 22);
+ comboBoxStop.Name = "comboBoxStop";
+ comboBoxStop.Size = new Size(230, 28);
+ comboBoxStop.TabIndex = 2;
+ //
+ // textBoxNumber
+ //
+ textBoxNumber.Location = new Point(114, 76);
+ textBoxNumber.Name = "textBoxNumber";
+ textBoxNumber.Size = new Size(230, 27);
+ textBoxNumber.TabIndex = 3;
+ //
+ // buttonSave
+ //
+ buttonSave.Location = new Point(134, 119);
+ buttonSave.Name = "buttonSave";
+ buttonSave.Size = new Size(94, 29);
+ buttonSave.TabIndex = 4;
+ buttonSave.Text = "Сохранить";
+ buttonSave.UseVisualStyleBackColor = true;
+ buttonSave.Click += buttonSave_Click;
+ //
+ // buttonCancel
+ //
+ buttonCancel.Location = new Point(250, 119);
+ buttonCancel.Name = "buttonCancel";
+ buttonCancel.Size = new Size(94, 29);
+ buttonCancel.TabIndex = 5;
+ buttonCancel.Text = "Отмена";
+ buttonCancel.UseVisualStyleBackColor = true;
+ buttonCancel.Click += buttonCancel_Click;
+ //
+ // FormRouteStop
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(366, 163);
+ Controls.Add(buttonCancel);
+ Controls.Add(buttonSave);
+ Controls.Add(textBoxNumber);
+ Controls.Add(comboBoxStop);
+ Controls.Add(labelNumber);
+ Controls.Add(labelStop);
+ Name = "FormRouteStop";
+ Text = "FormRouteStop";
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Label labelStop;
+ private Label labelNumber;
+ private ComboBox comboBoxStop;
+ private TextBox textBoxNumber;
+ private Button buttonSave;
+ private Button buttonCancel;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormRouteStop.cs b/RouteDirectory/RouteDirectoryForms/FormRouteStop.cs
new file mode 100644
index 0000000..a387a84
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRouteStop.cs
@@ -0,0 +1,124 @@
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using RouteDirectoryContracts.ViewModels;
+using RouteDirectoryDataModels.Models;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма для привязки остановки к маршруту
+ ///
+ public partial class FormRouteStop : Form
+ {
+ ///
+ /// Список остановок
+ ///
+ private readonly List? _list;
+
+ ///
+ /// Идентификатор остановки
+ ///
+ public int Id
+ {
+ get
+ {
+ return Convert.ToInt32(comboBoxStop.SelectedValue);
+ }
+ set
+ {
+ comboBoxStop.SelectedValue = value;
+ }
+ }
+
+ ///
+ /// Сущность "Остановка"
+ ///
+ public IStopModel? StopModel
+ {
+ get
+ {
+ if (_list == null)
+ {
+ return null;
+ }
+ foreach (var elem in _list)
+ {
+ if (elem.Id == Id)
+ {
+ return elem;
+ }
+ }
+ return null;
+ }
+ }
+
+ ///
+ /// Номер остановки в маршруте
+ ///
+ public int Number
+ {
+ get { return Convert.ToInt32(textBoxNumber.Text); }
+ set { textBoxNumber.Text = value.ToString(); }
+ }
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ public FormRouteStop(IStopLogic stopLogic)
+ {
+ InitializeComponent();
+
+ // Загрузка списка остановок для ComboBoxStop
+ _list = stopLogic.ReadList(null);
+ if (_list != null)
+ {
+ comboBoxStop.DisplayMember = "Name";
+ comboBoxStop.ValueMember = "Id";
+ comboBoxStop.DataSource = _list;
+ comboBoxStop.SelectedItem = null;
+ }
+ }
+
+ ///
+ /// Кнопка "Сохранить"
+ ///
+ ///
+ ///
+ private void buttonSave_Click(object sender, EventArgs e)
+ {
+ if (comboBoxStop.SelectedValue == null)
+ {
+ MessageBox.Show("Выберите остановку", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ if (string.IsNullOrEmpty(textBoxNumber.Text))
+ {
+ MessageBox.Show("Заполните номер остановки", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+
+ ///
+ /// Кнопка "Отмена"
+ ///
+ ///
+ ///
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormRouteStop.resx b/RouteDirectory/RouteDirectoryForms/FormRouteStop.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRouteStop.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoutes.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormRoutes.Designer.cs
new file mode 100644
index 0000000..a426164
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoutes.Designer.cs
@@ -0,0 +1,114 @@
+namespace RouteDirectoryView
+{
+ partial class FormRoutes
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ dataGridView = new DataGridView();
+ buttonCreate = new Button();
+ buttonUpdate = new Button();
+ buttonDelete = new Button();
+ buttonRefresh = new Button();
+ ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
+ SuspendLayout();
+ //
+ // dataGridView
+ //
+ dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ dataGridView.Location = new Point(1, 1);
+ dataGridView.Name = "dataGridView";
+ dataGridView.RowHeadersWidth = 51;
+ dataGridView.RowTemplate.Height = 29;
+ dataGridView.Size = new Size(665, 447);
+ dataGridView.TabIndex = 0;
+ //
+ // buttonCreate
+ //
+ buttonCreate.Location = new Point(685, 21);
+ buttonCreate.Name = "buttonCreate";
+ buttonCreate.Size = new Size(94, 29);
+ buttonCreate.TabIndex = 1;
+ buttonCreate.Text = "Создать";
+ buttonCreate.UseVisualStyleBackColor = true;
+ buttonCreate.Click += buttonCreate_Click;
+ //
+ // buttonUpdate
+ //
+ buttonUpdate.Location = new Point(685, 72);
+ buttonUpdate.Name = "buttonUpdate";
+ buttonUpdate.Size = new Size(94, 29);
+ buttonUpdate.TabIndex = 2;
+ buttonUpdate.Text = "Изменить";
+ buttonUpdate.UseVisualStyleBackColor = true;
+ buttonUpdate.Click += buttonUpdate_Click;
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(685, 123);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(94, 29);
+ buttonDelete.TabIndex = 3;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ buttonDelete.Click += buttonDelete_Click;
+ //
+ // buttonRefresh
+ //
+ buttonRefresh.Location = new Point(685, 173);
+ buttonRefresh.Name = "buttonRefresh";
+ buttonRefresh.Size = new Size(94, 29);
+ buttonRefresh.TabIndex = 4;
+ buttonRefresh.Text = "Обновить";
+ buttonRefresh.UseVisualStyleBackColor = true;
+ buttonRefresh.Click += buttonRefresh_Click;
+ //
+ // FormRoutes
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(796, 450);
+ Controls.Add(buttonRefresh);
+ Controls.Add(buttonDelete);
+ Controls.Add(buttonUpdate);
+ Controls.Add(buttonCreate);
+ Controls.Add(dataGridView);
+ Name = "FormRoutes";
+ Text = "Маршруты";
+ Load += FormRoutes_Load;
+ ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private DataGridView dataGridView;
+ private Button buttonCreate;
+ private Button buttonUpdate;
+ private Button buttonDelete;
+ private Button buttonRefresh;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoutes.cs b/RouteDirectory/RouteDirectoryForms/FormRoutes.cs
new file mode 100644
index 0000000..3f50e43
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoutes.cs
@@ -0,0 +1,157 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма для вывода списка маршрутов
+ ///
+ public partial class FormRoutes : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика
+ ///
+ private readonly IRouteLogic _routelogic;
+
+ ///
+ /// Конструктор
+ ///
+ public FormRoutes(ILogger logger, IRouteLogic routeLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _routelogic = routeLogic;
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ ///
+ ///
+ private void FormRoutes_Load(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Кнопка "Создать"
+ ///
+ ///
+ ///
+ private void buttonCreate_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormRoute));
+ if (service is FormRoute form)
+ {
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ LoadData();
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Изменить"
+ ///
+ ///
+ ///
+ private void buttonUpdate_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormRoute));
+ if (service is FormRoute form)
+ {
+ form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ LoadData();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Удалить"
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
+ {
+ int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
+ _logger.LogInformation("Удаление сущности 'Маршрут'");
+
+ try
+ {
+ if (!_routelogic.Delete(new RouteBindingModel { Id = id }))
+ {
+ throw new Exception("Ошибка при удалении сущности 'Маршрут'. Дополнительная информация в логах.");
+ }
+ LoadData();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка удаления сущности 'Маршрут'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Обновить"
+ ///
+ ///
+ ///
+ private void buttonRefresh_Click(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ private void LoadData()
+ {
+ try
+ {
+ var list = _routelogic.ReadList(null);
+ if (list != null)
+ {
+ dataGridView.DataSource = list;
+ dataGridView.Columns["Id"].Visible = false;
+ dataGridView.Columns["RouteStops"].Visible = false;
+ dataGridView.Columns["TransportId"].Visible = false;
+ dataGridView.Columns["Fare"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
+ dataGridView.Columns["RouteNumber"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
+ }
+ _logger.LogInformation("Загрузка списка маршрутов");
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка загрузки списка маршрутов");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoutes.resx b/RouteDirectory/RouteDirectoryForms/FormRoutes.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoutes.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoutesTests.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormRoutesTests.Designer.cs
new file mode 100644
index 0000000..3aeacbb
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoutesTests.Designer.cs
@@ -0,0 +1,230 @@
+namespace RouteDirectoryView
+{
+ partial class FormRoutesTests
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ numericUpDownDelete = new NumericUpDown();
+ numericUpDownRead = new NumericUpDown();
+ numericUpDownInsert = new NumericUpDown();
+ labelDelete = new Label();
+ labelRead = new Label();
+ labelInsert = new Label();
+ labelDeleteTime = new Label();
+ labelReadTime = new Label();
+ labelInsertTime = new Label();
+ buttonDelete = new Button();
+ buttonRead = new Button();
+ buttonInsert = new Button();
+ labelEntities3 = new Label();
+ labelEntities2 = new Label();
+ labelEntities1 = new Label();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownDelete).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownRead).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownInsert).BeginInit();
+ SuspendLayout();
+ //
+ // numericUpDownDelete
+ //
+ numericUpDownDelete.Location = new Point(104, 121);
+ numericUpDownDelete.Name = "numericUpDownDelete";
+ numericUpDownDelete.Size = new Size(114, 27);
+ numericUpDownDelete.TabIndex = 17;
+ //
+ // numericUpDownRead
+ //
+ numericUpDownRead.Location = new Point(104, 71);
+ numericUpDownRead.Name = "numericUpDownRead";
+ numericUpDownRead.Size = new Size(114, 27);
+ numericUpDownRead.TabIndex = 16;
+ //
+ // numericUpDownInsert
+ //
+ numericUpDownInsert.Location = new Point(104, 22);
+ numericUpDownInsert.Name = "numericUpDownInsert";
+ numericUpDownInsert.Size = new Size(114, 27);
+ numericUpDownInsert.TabIndex = 15;
+ //
+ // labelDelete
+ //
+ labelDelete.AutoSize = true;
+ labelDelete.Location = new Point(12, 123);
+ labelDelete.Name = "labelDelete";
+ labelDelete.Size = new Size(65, 20);
+ labelDelete.TabIndex = 14;
+ labelDelete.Text = "Удалить";
+ //
+ // labelRead
+ //
+ labelRead.AutoSize = true;
+ labelRead.Location = new Point(12, 71);
+ labelRead.Name = "labelRead";
+ labelRead.Size = new Size(75, 20);
+ labelRead.TabIndex = 13;
+ labelRead.Text = "Получить";
+ //
+ // labelInsert
+ //
+ labelInsert.AutoSize = true;
+ labelInsert.Location = new Point(12, 24);
+ labelInsert.Name = "labelInsert";
+ labelInsert.Size = new Size(64, 20);
+ labelInsert.TabIndex = 12;
+ labelInsert.Text = "Создать";
+ //
+ // labelDeleteTime
+ //
+ labelDeleteTime.AutoSize = true;
+ labelDeleteTime.Location = new Point(477, 124);
+ labelDeleteTime.Name = "labelDeleteTime";
+ labelDeleteTime.Size = new Size(255, 20);
+ labelDeleteTime.TabIndex = 29;
+ labelDeleteTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // labelReadTime
+ //
+ labelReadTime.AutoSize = true;
+ labelReadTime.Location = new Point(477, 77);
+ labelReadTime.Name = "labelReadTime";
+ labelReadTime.Size = new Size(255, 20);
+ labelReadTime.TabIndex = 28;
+ labelReadTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // labelInsertTime
+ //
+ labelInsertTime.AutoSize = true;
+ labelInsertTime.Location = new Point(477, 28);
+ labelInsertTime.Name = "labelInsertTime";
+ labelInsertTime.Size = new Size(255, 20);
+ labelInsertTime.TabIndex = 27;
+ labelInsertTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(340, 119);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(105, 29);
+ buttonDelete.TabIndex = 26;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ buttonDelete.Click += buttonDelete_Click;
+ //
+ // buttonRead
+ //
+ buttonRead.Location = new Point(340, 73);
+ buttonRead.Name = "buttonRead";
+ buttonRead.Size = new Size(105, 29);
+ buttonRead.TabIndex = 25;
+ buttonRead.Text = "Получить";
+ buttonRead.UseVisualStyleBackColor = true;
+ buttonRead.Click += buttonRead_Click;
+ //
+ // buttonInsert
+ //
+ buttonInsert.Location = new Point(340, 22);
+ buttonInsert.Name = "buttonInsert";
+ buttonInsert.Size = new Size(105, 29);
+ buttonInsert.TabIndex = 24;
+ buttonInsert.Text = "Создать";
+ buttonInsert.UseVisualStyleBackColor = true;
+ buttonInsert.Click += buttonInsert_Click;
+ //
+ // labelEntities3
+ //
+ labelEntities3.AutoSize = true;
+ labelEntities3.Location = new Point(242, 125);
+ labelEntities3.Name = "labelEntities3";
+ labelEntities3.Size = new Size(83, 20);
+ labelEntities3.TabIndex = 23;
+ labelEntities3.Text = "сущностей";
+ //
+ // labelEntities2
+ //
+ labelEntities2.AutoSize = true;
+ labelEntities2.Location = new Point(242, 73);
+ labelEntities2.Name = "labelEntities2";
+ labelEntities2.Size = new Size(83, 20);
+ labelEntities2.TabIndex = 22;
+ labelEntities2.Text = "сущностей";
+ //
+ // labelEntities1
+ //
+ labelEntities1.AutoSize = true;
+ labelEntities1.Location = new Point(242, 24);
+ labelEntities1.Name = "labelEntities1";
+ labelEntities1.Size = new Size(83, 20);
+ labelEntities1.TabIndex = 21;
+ labelEntities1.Text = "сущностей";
+ //
+ // FormRoutesTests
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(753, 170);
+ Controls.Add(labelDeleteTime);
+ Controls.Add(labelReadTime);
+ Controls.Add(labelInsertTime);
+ Controls.Add(buttonDelete);
+ Controls.Add(buttonRead);
+ Controls.Add(buttonInsert);
+ Controls.Add(labelEntities3);
+ Controls.Add(labelEntities2);
+ Controls.Add(labelEntities1);
+ Controls.Add(numericUpDownDelete);
+ Controls.Add(numericUpDownRead);
+ Controls.Add(numericUpDownInsert);
+ Controls.Add(labelDelete);
+ Controls.Add(labelRead);
+ Controls.Add(labelInsert);
+ Name = "FormRoutesTests";
+ Text = " Тесты для сущности \"Маршрут\"";
+ ((System.ComponentModel.ISupportInitialize)numericUpDownDelete).EndInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownRead).EndInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownInsert).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private NumericUpDown numericUpDownDelete;
+ private NumericUpDown numericUpDownRead;
+ private NumericUpDown numericUpDownInsert;
+ private Label labelDelete;
+ private Label labelRead;
+ private Label labelInsert;
+ private Label labelDeleteTime;
+ private Label labelReadTime;
+ private Label labelInsertTime;
+ private Button buttonDelete;
+ private Button buttonRead;
+ private Button buttonInsert;
+ private Label labelEntities3;
+ private Label labelEntities2;
+ private Label labelEntities1;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoutesTests.cs b/RouteDirectory/RouteDirectoryForms/FormRoutesTests.cs
new file mode 100644
index 0000000..86921dc
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoutesTests.cs
@@ -0,0 +1,151 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма с тестами для сущности "Маршрут"
+ ///
+ public partial class FormRoutesTests : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика для маршрутов
+ ///
+ private readonly IRouteLogic _routeLogic;
+
+ ///
+ /// Бизнес-логика для транспорта
+ ///
+ private readonly ITransportTypeLogic _transportLogic;
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ ///
+ ///
+ public FormRoutesTests(ILogger logger, IRouteLogic routeLogic, ITransportTypeLogic transportLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _routeLogic = routeLogic;
+ _transportLogic = transportLogic;
+
+ numericUpDownInsert.Maximum = 10000;
+ numericUpDownRead.Maximum = 10000;
+ numericUpDownDelete.Maximum = 10000;
+ }
+
+ ///
+ /// Кнопка "Создать"
+ ///
+ ///
+ ///
+ private void buttonInsert_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownInsert.Value);
+ _logger.LogInformation("RouteInsertTest. Count: {Count}", entitiesCount);
+ try
+ {
+ double time = 0;
+ var stopwatch = new Stopwatch();
+ int transportId = _transportLogic.ReadList(1)![0].Id;
+ for (int i = 1; i <= entitiesCount; i++)
+ {
+ var model = new RouteBindingModel
+ {
+ Id = 0,
+ RouteNumber = $"Маршрут {i}",
+ TransportId = transportId
+ };
+
+ stopwatch.Restart();
+ var operationResult = _routeLogic.Create(model);
+ if (!operationResult)
+ {
+ throw new Exception("Ошибка при сохранении сущности 'Маршрут'. Дополнительная информация в логах.");
+ }
+ stopwatch.Stop();
+ time += stopwatch.ElapsedMilliseconds;
+ }
+ labelInsertTime.Text = $"Total time: {Convert.ToInt32(time)} ms / Average time: {Convert.ToInt32(time / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "RouteInsertTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Получить"
+ ///
+ ///
+ ///
+ private void buttonRead_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownRead.Value);
+ _logger.LogInformation("RouteReadTest. Count: {Count}", entitiesCount);
+ try
+ {
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
+ _routeLogic.ReadList(entitiesCount);
+ stopwatch.Stop();
+ labelReadTime.Text = $"Total time: {Convert.ToInt32(stopwatch.ElapsedMilliseconds)} ms / Average time: {Convert.ToInt32(stopwatch.ElapsedMilliseconds / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "RouteReadTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Удалить"
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownDelete.Value);
+ _logger.LogInformation("RouteDeleteTest. Count: {Count}", entitiesCount);
+ try
+ {
+ double time = 0;
+ var stopwatch = new Stopwatch();
+ for (int i = 1; i <= entitiesCount; i++)
+ {
+ stopwatch.Restart();
+ _routeLogic.Delete();
+ stopwatch.Stop();
+ time += stopwatch.ElapsedMilliseconds;
+ }
+ labelDeleteTime.Text = $"Total time: {Convert.ToInt32(time)} ms / Average time: {Convert.ToInt32(time / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "RouteDeleteTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormRoutesTests.resx b/RouteDirectory/RouteDirectoryForms/FormRoutesTests.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormRoutesTests.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormSchedule.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormSchedule.Designer.cs
new file mode 100644
index 0000000..d39aa76
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormSchedule.Designer.cs
@@ -0,0 +1,163 @@
+namespace RouteDirectoryView
+{
+ partial class FormSchedule
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ labelRoute = new Label();
+ labelStart = new Label();
+ labelEnd = new Label();
+ labelTrafficInterval = new Label();
+ comboBoxRoute = new ComboBox();
+ dateTimePickerStart = new DateTimePicker();
+ dateTimePickerEnd = new DateTimePicker();
+ dateTimePickerTrafficInterval = new DateTimePicker();
+ buttonSave = new Button();
+ buttonCancel = new Button();
+ SuspendLayout();
+ //
+ // labelRoute
+ //
+ labelRoute.AutoSize = true;
+ labelRoute.Location = new Point(22, 24);
+ labelRoute.Name = "labelRoute";
+ labelRoute.Size = new Size(73, 20);
+ labelRoute.TabIndex = 0;
+ labelRoute.Text = "Маршрут";
+ //
+ // labelStart
+ //
+ labelStart.AutoSize = true;
+ labelStart.Location = new Point(22, 75);
+ labelStart.Name = "labelStart";
+ labelStart.Size = new Size(102, 20);
+ labelStart.TabIndex = 1;
+ labelStart.Text = "Отправление";
+ //
+ // labelEnd
+ //
+ labelEnd.AutoSize = true;
+ labelEnd.Location = new Point(22, 131);
+ labelEnd.Name = "labelEnd";
+ labelEnd.Size = new Size(81, 20);
+ labelEnd.TabIndex = 2;
+ labelEnd.Text = "Прибытие";
+ //
+ // labelTrafficInterval
+ //
+ labelTrafficInterval.AutoSize = true;
+ labelTrafficInterval.Location = new Point(22, 186);
+ labelTrafficInterval.Name = "labelTrafficInterval";
+ labelTrafficInterval.Size = new Size(119, 20);
+ labelTrafficInterval.TabIndex = 3;
+ labelTrafficInterval.Text = "Периодичность";
+ //
+ // comboBoxRoute
+ //
+ comboBoxRoute.FormattingEnabled = true;
+ comboBoxRoute.Location = new Point(200, 21);
+ comboBoxRoute.Name = "comboBoxRoute";
+ comboBoxRoute.Size = new Size(250, 28);
+ comboBoxRoute.TabIndex = 4;
+ //
+ // dateTimePickerStart
+ //
+ dateTimePickerStart.Location = new Point(200, 75);
+ dateTimePickerStart.Name = "dateTimePickerStart";
+ dateTimePickerStart.Size = new Size(250, 27);
+ dateTimePickerStart.TabIndex = 5;
+ //
+ // dateTimePickerEnd
+ //
+ dateTimePickerEnd.Location = new Point(200, 126);
+ dateTimePickerEnd.Name = "dateTimePickerEnd";
+ dateTimePickerEnd.Size = new Size(250, 27);
+ dateTimePickerEnd.TabIndex = 6;
+ //
+ // dateTimePickerTrafficInterval
+ //
+ dateTimePickerTrafficInterval.Location = new Point(200, 179);
+ dateTimePickerTrafficInterval.Name = "dateTimePickerTrafficInterval";
+ dateTimePickerTrafficInterval.Size = new Size(250, 27);
+ dateTimePickerTrafficInterval.TabIndex = 7;
+ //
+ // buttonSave
+ //
+ buttonSave.Location = new Point(243, 235);
+ buttonSave.Name = "buttonSave";
+ buttonSave.Size = new Size(94, 29);
+ buttonSave.TabIndex = 8;
+ buttonSave.Text = "Сохранить";
+ buttonSave.UseVisualStyleBackColor = true;
+ buttonSave.Click += buttonSave_Click;
+ //
+ // buttonCancel
+ //
+ buttonCancel.Location = new Point(356, 235);
+ buttonCancel.Name = "buttonCancel";
+ buttonCancel.Size = new Size(94, 29);
+ buttonCancel.TabIndex = 9;
+ buttonCancel.Text = "Отмена";
+ buttonCancel.UseVisualStyleBackColor = true;
+ buttonCancel.Click += buttonCancel_Click;
+ //
+ // FormSchedule
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(469, 275);
+ Controls.Add(buttonCancel);
+ Controls.Add(buttonSave);
+ Controls.Add(dateTimePickerTrafficInterval);
+ Controls.Add(dateTimePickerEnd);
+ Controls.Add(dateTimePickerStart);
+ Controls.Add(comboBoxRoute);
+ Controls.Add(labelTrafficInterval);
+ Controls.Add(labelEnd);
+ Controls.Add(labelStart);
+ Controls.Add(labelRoute);
+ Name = "FormSchedule";
+ Text = "FormSchedule";
+ Load += FormSchedule_Load;
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Label labelRoute;
+ private Label labelStart;
+ private Label labelEnd;
+ private Label labelTrafficInterval;
+ private ComboBox comboBoxRoute;
+ private DateTimePicker dateTimePickerStart;
+ private DateTimePicker dateTimePickerEnd;
+ private DateTimePicker dateTimePickerTrafficInterval;
+ private Button buttonSave;
+ private Button buttonCancel;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormSchedule.cs b/RouteDirectory/RouteDirectoryForms/FormSchedule.cs
new file mode 100644
index 0000000..2144c28
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormSchedule.cs
@@ -0,0 +1,170 @@
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using RouteDirectoryContracts.SearchModels;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ public partial class FormSchedule : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика для расписаний
+ ///
+ private readonly IScheduleLogic _scheduleLogic;
+
+ ///
+ /// Бизнес-логика для маршрутов
+ ///
+ private readonly IRouteLogic _routeLogic;
+
+ ///
+ /// Идентификатор
+ ///
+ private int? _id;
+
+ ///
+ /// Идентификатор
+ ///
+ public int Id { set { _id = value; } }
+
+ ///
+ /// Констурктор
+ ///
+ ///
+ ///
+ ///
+ public FormSchedule(ILogger logger, IScheduleLogic scheduleLogic, IRouteLogic routeLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _scheduleLogic = scheduleLogic;
+ _routeLogic = routeLogic;
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ ///
+ ///
+ private void FormSchedule_Load(object sender, EventArgs e)
+ {
+ try
+ {
+ // Загрузка маршрутов для ComboBoxRoute
+ _logger.LogInformation("Загрузка списка маршрутов");
+ var list = _routeLogic.ReadList(null);
+ if (list != null)
+ {
+ comboBoxRoute.DisplayMember = "Name";
+ comboBoxRoute.ValueMember = "Id";
+ comboBoxRoute.DataSource = list;
+ comboBoxRoute.SelectedItem = null;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка загрузки списка маршрутов");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+
+ if (!_id.HasValue)
+ {
+ return;
+ }
+
+ try
+ {
+ // Заполнение полей
+ _logger.LogInformation("Получение сущности 'Расписание'");
+ var view = _scheduleLogic.ReadElement(new ScheduleSearchModel
+ {
+ Id = _id.Value
+ });
+ if (view != null)
+ {
+ comboBoxRoute.SelectedItem = view.RouteId;
+ dateTimePickerStart.Value = view.StartTime;
+ dateTimePickerEnd.Value = view.EndTime;
+ dateTimePickerTrafficInterval.Value = view.TrafficInterval;
+ }
+ }
+ catch (Exception ex1)
+ {
+ _logger.LogError(ex1, "Ошибка получения сущности 'Расписание'");
+ MessageBox.Show(ex1.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Сохранить"
+ ///
+ ///
+ ///
+ private void buttonSave_Click(object sender, EventArgs e)
+ {
+ if (comboBoxRoute.SelectedValue == null)
+ {
+ MessageBox.Show("Выберите маршрут", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ if (dateTimePickerStart.Value >= dateTimePickerEnd.Value)
+ {
+ MessageBox.Show("Время прибытия должно опережать время отправления", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ _logger.LogInformation("Сохранение сущности 'Расписание'");
+ try
+ {
+ var model = new ScheduleBindingModel
+ {
+ Id = _id ?? 0,
+ StartTime = dateTimePickerStart.Value,
+ EndTime = dateTimePickerEnd.Value,
+ TrafficInterval = dateTimePickerTrafficInterval.Value,
+ RouteId = Convert.ToInt32(comboBoxRoute.SelectedValue)
+ };
+
+ var operationResult = _id.HasValue ? _scheduleLogic.Update(model) : _scheduleLogic.Create(model);
+ if (!operationResult)
+ {
+ throw new Exception("Ошибка при сохранении сущности 'Расписание'. Дополнительная информация в логах.");
+ }
+
+ MessageBox.Show("Сохранение сущности 'Расписание' прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка сохранения сущности 'Расписание'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Отмена"
+ ///
+ ///
+ ///
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormSchedule.resx b/RouteDirectory/RouteDirectoryForms/FormSchedule.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormSchedule.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.Designer.cs
new file mode 100644
index 0000000..445e6fa
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.Designer.cs
@@ -0,0 +1,232 @@
+namespace RouteDirectoryView
+{
+ partial class FormSchedulesTests
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ labelInsert = new Label();
+ labelDelete = new Label();
+ labelRead = new Label();
+ numericUpDownDelete = new NumericUpDown();
+ numericUpDownRead = new NumericUpDown();
+ numericUpDownInsert = new NumericUpDown();
+ labelEntities3 = new Label();
+ labelEntities2 = new Label();
+ labelEntities1 = new Label();
+ buttonDelete = new Button();
+ buttonRead = new Button();
+ buttonInsert = new Button();
+ labelDeleteTime = new Label();
+ labelReadTime = new Label();
+ labelInsertTime = new Label();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownDelete).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownRead).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownInsert).BeginInit();
+ SuspendLayout();
+ //
+ // labelInsert
+ //
+ labelInsert.AutoSize = true;
+ labelInsert.Location = new Point(12, 19);
+ labelInsert.Name = "labelInsert";
+ labelInsert.Size = new Size(64, 20);
+ labelInsert.TabIndex = 1;
+ labelInsert.Text = "Создать";
+ //
+ // labelDelete
+ //
+ labelDelete.AutoSize = true;
+ labelDelete.Location = new Point(12, 118);
+ labelDelete.Name = "labelDelete";
+ labelDelete.Size = new Size(65, 20);
+ labelDelete.TabIndex = 4;
+ labelDelete.Text = "Удалить";
+ //
+ // labelRead
+ //
+ labelRead.AutoSize = true;
+ labelRead.Location = new Point(12, 66);
+ labelRead.Name = "labelRead";
+ labelRead.Size = new Size(75, 20);
+ labelRead.TabIndex = 3;
+ labelRead.Text = "Получить";
+ //
+ // numericUpDownDelete
+ //
+ numericUpDownDelete.Location = new Point(104, 116);
+ numericUpDownDelete.Name = "numericUpDownDelete";
+ numericUpDownDelete.Size = new Size(114, 27);
+ numericUpDownDelete.TabIndex = 11;
+ //
+ // numericUpDownRead
+ //
+ numericUpDownRead.Location = new Point(104, 66);
+ numericUpDownRead.Name = "numericUpDownRead";
+ numericUpDownRead.Size = new Size(114, 27);
+ numericUpDownRead.TabIndex = 10;
+ //
+ // numericUpDownInsert
+ //
+ numericUpDownInsert.Location = new Point(104, 17);
+ numericUpDownInsert.Name = "numericUpDownInsert";
+ numericUpDownInsert.Size = new Size(114, 27);
+ numericUpDownInsert.TabIndex = 9;
+ //
+ // labelEntities3
+ //
+ labelEntities3.AutoSize = true;
+ labelEntities3.Location = new Point(245, 120);
+ labelEntities3.Name = "labelEntities3";
+ labelEntities3.Size = new Size(83, 20);
+ labelEntities3.TabIndex = 14;
+ labelEntities3.Text = "сущностей";
+ //
+ // labelEntities2
+ //
+ labelEntities2.AutoSize = true;
+ labelEntities2.Location = new Point(245, 68);
+ labelEntities2.Name = "labelEntities2";
+ labelEntities2.Size = new Size(83, 20);
+ labelEntities2.TabIndex = 13;
+ labelEntities2.Text = "сущностей";
+ //
+ // labelEntities1
+ //
+ labelEntities1.AutoSize = true;
+ labelEntities1.Location = new Point(245, 19);
+ labelEntities1.Name = "labelEntities1";
+ labelEntities1.Size = new Size(83, 20);
+ labelEntities1.TabIndex = 12;
+ labelEntities1.Text = "сущностей";
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(343, 114);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(105, 29);
+ buttonDelete.TabIndex = 17;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ buttonDelete.Click += buttonDelete_Click;
+ //
+ // buttonRead
+ //
+ buttonRead.Location = new Point(343, 68);
+ buttonRead.Name = "buttonRead";
+ buttonRead.Size = new Size(105, 29);
+ buttonRead.TabIndex = 16;
+ buttonRead.Text = "Получить";
+ buttonRead.UseVisualStyleBackColor = true;
+ buttonRead.Click += buttonRead_Click;
+ //
+ // buttonInsert
+ //
+ buttonInsert.Location = new Point(343, 17);
+ buttonInsert.Name = "buttonInsert";
+ buttonInsert.Size = new Size(105, 29);
+ buttonInsert.TabIndex = 15;
+ buttonInsert.Text = "Создать";
+ buttonInsert.UseVisualStyleBackColor = true;
+ buttonInsert.Click += buttonInsert_Click;
+ //
+ // labelDeleteTime
+ //
+ labelDeleteTime.AutoSize = true;
+ labelDeleteTime.Location = new Point(480, 119);
+ labelDeleteTime.Name = "labelDeleteTime";
+ labelDeleteTime.Size = new Size(255, 20);
+ labelDeleteTime.TabIndex = 20;
+ labelDeleteTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // labelReadTime
+ //
+ labelReadTime.AutoSize = true;
+ labelReadTime.Location = new Point(480, 72);
+ labelReadTime.Name = "labelReadTime";
+ labelReadTime.Size = new Size(255, 20);
+ labelReadTime.TabIndex = 19;
+ labelReadTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // labelInsertTime
+ //
+ labelInsertTime.AutoSize = true;
+ labelInsertTime.Location = new Point(480, 23);
+ labelInsertTime.Name = "labelInsertTime";
+ labelInsertTime.Size = new Size(255, 20);
+ labelInsertTime.TabIndex = 18;
+ labelInsertTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // FormSchedulesTests
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(751, 166);
+ Controls.Add(labelDeleteTime);
+ Controls.Add(labelReadTime);
+ Controls.Add(labelInsertTime);
+ Controls.Add(buttonDelete);
+ Controls.Add(buttonRead);
+ Controls.Add(buttonInsert);
+ Controls.Add(labelEntities3);
+ Controls.Add(labelEntities2);
+ Controls.Add(labelEntities1);
+ Controls.Add(numericUpDownDelete);
+ Controls.Add(numericUpDownRead);
+ Controls.Add(numericUpDownInsert);
+ Controls.Add(labelDelete);
+ Controls.Add(labelRead);
+ Controls.Add(labelInsert);
+ Name = "FormSchedulesTests";
+ Text = " Тесты для сущности \"Расписание\"";
+ Load += FormSchedulesTests_Load;
+ Click += FormSchedulesTests_Load;
+ ((System.ComponentModel.ISupportInitialize)numericUpDownDelete).EndInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownRead).EndInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownInsert).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Label labelInsert;
+ private Label labelDelete;
+ private Label labelRead;
+ private NumericUpDown numericUpDownDelete;
+ private NumericUpDown numericUpDownRead;
+ private NumericUpDown numericUpDownInsert;
+ private Label labelEntities3;
+ private Label labelEntities2;
+ private Label labelEntities1;
+ private Button buttonDelete;
+ private Button buttonRead;
+ private Button buttonInsert;
+ private Label labelDeleteTime;
+ private Label labelReadTime;
+ private Label labelInsertTime;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.cs b/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.cs
new file mode 100644
index 0000000..ffd45ba
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.cs
@@ -0,0 +1,158 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма с тестами для сущности "Расписание"
+ ///
+ public partial class FormSchedulesTests : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика для расписания
+ ///
+ private readonly IScheduleLogic _scheduleLogic;
+
+ ///
+ /// Бизнес-логика для маршрутов
+ ///
+ private readonly IRouteLogic _routeLogic;
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ ///
+ ///
+ public FormSchedulesTests(ILogger logger, IScheduleLogic scheduleLogic, IRouteLogic routeLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _scheduleLogic = scheduleLogic;
+ _routeLogic = routeLogic;
+
+ numericUpDownInsert.Maximum = 10000;
+ numericUpDownRead.Maximum = 10000;
+ numericUpDownDelete.Maximum = 10000;
+ }
+
+ ///
+ /// Кнопка "Создать"
+ ///
+ ///
+ ///
+ private void buttonInsert_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownInsert.Value);
+ _logger.LogInformation("ScheduleInsertTest. Count: {Count}", entitiesCount);
+ try
+ {
+ double time = 0;
+ var stopwatch = new Stopwatch();
+ int routeId = _routeLogic.ReadList(1)![0].Id;
+ for (int i = 1; i <= entitiesCount; i++)
+ {
+ var model = new ScheduleBindingModel
+ {
+ Id = 0,
+ StartTime = DateTime.MinValue,
+ EndTime = DateTime.MaxValue,
+ TrafficInterval = DateTime.MinValue,
+ RouteId = routeId
+ };
+
+ stopwatch.Restart();
+ var operationResult = _scheduleLogic.Create(model);
+ if (!operationResult)
+ {
+ throw new Exception("Ошибка при сохранении сущности 'Расписание'. Дополнительная информация в логах.");
+ }
+ stopwatch.Stop();
+ time += stopwatch.ElapsedMilliseconds;
+ }
+ labelInsertTime.Text = $"Total time: {Convert.ToInt32(time)} ms / Average time: {Convert.ToInt32(time / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "ScheduleInsertTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Получить"
+ ///
+ ///
+ ///
+ private void buttonRead_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownRead.Value);
+ _logger.LogInformation("ScheduleReadTest. Count: {Count}", entitiesCount);
+ try
+ {
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
+ _scheduleLogic.ReadList(entitiesCount);
+ stopwatch.Stop();
+ labelReadTime.Text = $"Total time: {Convert.ToInt32(stopwatch.ElapsedMilliseconds)} ms / Average time: {Convert.ToInt32(stopwatch.ElapsedMilliseconds / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "ScheduleReadTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Удалить"
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownDelete.Value);
+ _logger.LogInformation("ScheduleDeleteTest. Count: {Count}", entitiesCount);
+ try
+ {
+ double time = 0;
+ var stopwatch = new Stopwatch();
+ for (int i = 1; i <= entitiesCount; i++)
+ {
+ stopwatch.Restart();
+ _scheduleLogic.Delete();
+ stopwatch.Stop();
+ time += stopwatch.ElapsedMilliseconds;
+ }
+ labelDeleteTime.Text = $"Total time: {Convert.ToInt32(time)} ms / Average time: {Convert.ToInt32(time / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "ScheduleDeleteTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ private void FormSchedulesTests_Load(object sender, EventArgs e)
+ {
+
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.resx b/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormSchedulesTests.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormStop.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormStop.Designer.cs
new file mode 100644
index 0000000..31145bf
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStop.Designer.cs
@@ -0,0 +1,96 @@
+namespace RouteDirectoryView
+{
+ partial class FormStop
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ labelName = new Label();
+ textBoxName = new TextBox();
+ button1 = new Button();
+ button2 = new Button();
+ SuspendLayout();
+ //
+ // labelName
+ //
+ labelName.AutoSize = true;
+ labelName.Location = new Point(12, 28);
+ labelName.Name = "labelName";
+ labelName.Size = new Size(80, 20);
+ labelName.TabIndex = 0;
+ labelName.Text = "Название:";
+ //
+ // textBoxName
+ //
+ textBoxName.Location = new Point(107, 25);
+ textBoxName.Name = "textBoxName";
+ textBoxName.Size = new Size(219, 27);
+ textBoxName.TabIndex = 3;
+ //
+ // button1
+ //
+ button1.Location = new Point(118, 70);
+ button1.Name = "button1";
+ button1.Size = new Size(94, 29);
+ button1.TabIndex = 6;
+ button1.Text = "Сохранить";
+ button1.UseVisualStyleBackColor = true;
+ button1.Click += buttonSave_Click;
+ //
+ // button2
+ //
+ button2.Location = new Point(232, 70);
+ button2.Name = "button2";
+ button2.Size = new Size(94, 29);
+ button2.TabIndex = 7;
+ button2.Text = "Отмена";
+ button2.UseVisualStyleBackColor = true;
+ button2.Click += buttonCancel_Click;
+ //
+ // FormStop
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(342, 114);
+ Controls.Add(button2);
+ Controls.Add(button1);
+ Controls.Add(textBoxName);
+ Controls.Add(labelName);
+ Name = "FormStop";
+ Text = "Остановка";
+ Load += FormStop_Load;
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Label labelName;
+ private TextBox textBoxName;
+ private Button button1;
+ private Button button2;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormStop.cs b/RouteDirectory/RouteDirectoryForms/FormStop.cs
new file mode 100644
index 0000000..7456e07
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStop.cs
@@ -0,0 +1,134 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using RouteDirectoryContracts.SearchModels;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма для создания/редактирования остановок
+ ///
+ public partial class FormStop : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика
+ ///
+ private readonly IStopLogic _stopLogic;
+
+ ///
+ /// Идентификатор
+ ///
+ private int? _id;
+
+ ///
+ /// Идентификатор
+ ///
+ public int Id { set { _id = value; } }
+
+ ///
+ /// Конструктор
+ ///
+ public FormStop(ILogger logger, IStopLogic stopLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _stopLogic = stopLogic;
+ }
+
+ ///
+ /// Загрузка информации о сущности
+ ///
+ ///
+ ///
+ private void FormStop_Load(object sender, EventArgs e)
+ {
+ if (!_id.HasValue)
+ {
+ return;
+ }
+
+ try
+ {
+ _logger.LogInformation("Получение сущности 'Остановка'");
+ var view = _stopLogic.ReadElement(new StopSearchModel
+ {
+ Id = _id.Value
+ });
+ if (view != null)
+ {
+ textBoxName.Text = view.Name;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка получения сущности 'Остановка'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Сохранить"
+ ///
+ ///
+ ///
+ private void buttonSave_Click(object sender, EventArgs e)
+ {
+ if (string.IsNullOrEmpty(textBoxName.Text))
+ {
+ MessageBox.Show("Заполните название остановки", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ _logger.LogInformation("Сохранение сущности 'Остановка'");
+ try
+ {
+ var model = new StopBindingModel
+ {
+ Id = _id ?? 0,
+ Name = textBoxName.Text
+ };
+
+ var operationResult = _id.HasValue ? _stopLogic.Update(model) : _stopLogic.Create(model);
+ if (!operationResult)
+ {
+ throw new Exception("Ошибка при сохранении сущности 'Остановка'. Дополнительная информация в логах.");
+ }
+
+ MessageBox.Show("Сохранение сущности 'Остановка' прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка сохранения сущности 'Остановка'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Отмена"
+ ///
+ ///
+ ///
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormStop.resx b/RouteDirectory/RouteDirectoryForms/FormStop.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStop.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormStops.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormStops.Designer.cs
new file mode 100644
index 0000000..6e84c13
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStops.Designer.cs
@@ -0,0 +1,114 @@
+namespace RouteDirectoryView
+{
+ partial class FormStops
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ dataGridView = new DataGridView();
+ buttonCreate = new Button();
+ buttonUpdate = new Button();
+ buttonDelete = new Button();
+ buttonRefresh = new Button();
+ ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
+ SuspendLayout();
+ //
+ // dataGridView
+ //
+ dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ dataGridView.Location = new Point(0, -2);
+ dataGridView.Name = "dataGridView";
+ dataGridView.RowHeadersWidth = 51;
+ dataGridView.RowTemplate.Height = 29;
+ dataGridView.Size = new Size(662, 450);
+ dataGridView.TabIndex = 0;
+ //
+ // buttonCreate
+ //
+ buttonCreate.Location = new Point(685, 23);
+ buttonCreate.Name = "buttonCreate";
+ buttonCreate.Size = new Size(94, 29);
+ buttonCreate.TabIndex = 1;
+ buttonCreate.Text = "Создать";
+ buttonCreate.UseVisualStyleBackColor = true;
+ buttonCreate.Click += buttonCreate_Click;
+ //
+ // buttonUpdate
+ //
+ buttonUpdate.Location = new Point(685, 72);
+ buttonUpdate.Name = "buttonUpdate";
+ buttonUpdate.Size = new Size(94, 29);
+ buttonUpdate.TabIndex = 2;
+ buttonUpdate.Text = "Изменить";
+ buttonUpdate.UseVisualStyleBackColor = true;
+ buttonUpdate.Click += buttonUpdate_Click;
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(685, 125);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(94, 29);
+ buttonDelete.TabIndex = 3;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ buttonDelete.Click += buttonDelete_Click;
+ //
+ // buttonRefresh
+ //
+ buttonRefresh.Location = new Point(685, 175);
+ buttonRefresh.Name = "buttonRefresh";
+ buttonRefresh.Size = new Size(94, 29);
+ buttonRefresh.TabIndex = 4;
+ buttonRefresh.Text = "Обновить";
+ buttonRefresh.UseVisualStyleBackColor = true;
+ buttonRefresh.Click += buttonRefresh_Click;
+ //
+ // FormStops
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(800, 450);
+ Controls.Add(buttonRefresh);
+ Controls.Add(buttonDelete);
+ Controls.Add(buttonUpdate);
+ Controls.Add(buttonCreate);
+ Controls.Add(dataGridView);
+ Name = "FormStops";
+ Text = "Остановки";
+ Load += FormStops_Load;
+ ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private DataGridView dataGridView;
+ private Button buttonCreate;
+ private Button buttonUpdate;
+ private Button buttonDelete;
+ private Button buttonRefresh;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormStops.cs b/RouteDirectory/RouteDirectoryForms/FormStops.cs
new file mode 100644
index 0000000..4c78709
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStops.cs
@@ -0,0 +1,154 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма для вывода списка остановок
+ ///
+ public partial class FormStops : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика
+ ///
+ private readonly IStopLogic _stoplogic;
+
+ ///
+ /// Конструктор
+ ///
+ public FormStops(ILogger logger, IStopLogic stopLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _stoplogic = stopLogic;
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ ///
+ ///
+ private void FormStops_Load(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Кнопка "Создать"
+ ///
+ ///
+ ///
+ private void buttonCreate_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormStop));
+ if (service is FormStop form)
+ {
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ LoadData();
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Изменить"
+ ///
+ ///
+ ///
+ private void buttonUpdate_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormStop));
+ if (service is FormStop form)
+ {
+ form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ LoadData();
+ }
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
+ {
+ int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
+ _logger.LogInformation("Удаление сущности 'Остановка'");
+
+ try
+ {
+ if (!_stoplogic.Delete(new StopBindingModel { Id = id }))
+ {
+ throw new Exception("Ошибка при удалении сущности 'Остановка'. Дополнительная информация в логах.");
+ }
+ LoadData();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка удаления сущности 'Остановка'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Обновить"
+ ///
+ ///
+ ///
+ private void buttonRefresh_Click(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ private void LoadData()
+ {
+ try
+ {
+ var list = _stoplogic.ReadList(null);
+ if (list != null)
+ {
+ dataGridView.DataSource = list;
+ dataGridView.Columns["Id"].Visible = false;
+ dataGridView.Columns["Name"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
+ }
+ _logger.LogInformation("Загрузка списка остановок");
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка загрузки списка остановок");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormStops.resx b/RouteDirectory/RouteDirectoryForms/FormStops.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStops.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormStopsTests.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormStopsTests.Designer.cs
new file mode 100644
index 0000000..bda4cf6
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStopsTests.Designer.cs
@@ -0,0 +1,230 @@
+namespace RouteDirectoryView
+{
+ partial class FormStopsTests
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ labelDelete = new Label();
+ labelRead = new Label();
+ labelInsert = new Label();
+ numericUpDownDelete = new NumericUpDown();
+ numericUpDownRead = new NumericUpDown();
+ numericUpDownInsert = new NumericUpDown();
+ labelEntities3 = new Label();
+ labelEntities2 = new Label();
+ labelEntities1 = new Label();
+ buttonDelete = new Button();
+ buttonRead = new Button();
+ buttonInsert = new Button();
+ labelDeleteTime = new Label();
+ labelReadTime = new Label();
+ labelInsertTime = new Label();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownDelete).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownRead).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownInsert).BeginInit();
+ SuspendLayout();
+ //
+ // labelDelete
+ //
+ labelDelete.AutoSize = true;
+ labelDelete.Location = new Point(12, 117);
+ labelDelete.Name = "labelDelete";
+ labelDelete.Size = new Size(65, 20);
+ labelDelete.TabIndex = 7;
+ labelDelete.Text = "Удалить";
+ //
+ // labelRead
+ //
+ labelRead.AutoSize = true;
+ labelRead.Location = new Point(12, 65);
+ labelRead.Name = "labelRead";
+ labelRead.Size = new Size(75, 20);
+ labelRead.TabIndex = 6;
+ labelRead.Text = "Получить";
+ //
+ // labelInsert
+ //
+ labelInsert.AutoSize = true;
+ labelInsert.Location = new Point(12, 18);
+ labelInsert.Name = "labelInsert";
+ labelInsert.Size = new Size(64, 20);
+ labelInsert.TabIndex = 5;
+ labelInsert.Text = "Создать";
+ //
+ // numericUpDownDelete
+ //
+ numericUpDownDelete.Location = new Point(102, 115);
+ numericUpDownDelete.Name = "numericUpDownDelete";
+ numericUpDownDelete.Size = new Size(114, 27);
+ numericUpDownDelete.TabIndex = 14;
+ //
+ // numericUpDownRead
+ //
+ numericUpDownRead.Location = new Point(102, 65);
+ numericUpDownRead.Name = "numericUpDownRead";
+ numericUpDownRead.Size = new Size(114, 27);
+ numericUpDownRead.TabIndex = 13;
+ //
+ // numericUpDownInsert
+ //
+ numericUpDownInsert.Location = new Point(102, 16);
+ numericUpDownInsert.Name = "numericUpDownInsert";
+ numericUpDownInsert.Size = new Size(114, 27);
+ numericUpDownInsert.TabIndex = 12;
+ //
+ // labelEntities3
+ //
+ labelEntities3.AutoSize = true;
+ labelEntities3.Location = new Point(234, 119);
+ labelEntities3.Name = "labelEntities3";
+ labelEntities3.Size = new Size(83, 20);
+ labelEntities3.TabIndex = 17;
+ labelEntities3.Text = "сущностей";
+ //
+ // labelEntities2
+ //
+ labelEntities2.AutoSize = true;
+ labelEntities2.Location = new Point(234, 67);
+ labelEntities2.Name = "labelEntities2";
+ labelEntities2.Size = new Size(83, 20);
+ labelEntities2.TabIndex = 16;
+ labelEntities2.Text = "сущностей";
+ //
+ // labelEntities1
+ //
+ labelEntities1.AutoSize = true;
+ labelEntities1.Location = new Point(234, 18);
+ labelEntities1.Name = "labelEntities1";
+ labelEntities1.Size = new Size(83, 20);
+ labelEntities1.TabIndex = 15;
+ labelEntities1.Text = "сущностей";
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(337, 115);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(105, 29);
+ buttonDelete.TabIndex = 20;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ buttonDelete.Click += buttonDelete_Click;
+ //
+ // buttonRead
+ //
+ buttonRead.Location = new Point(337, 65);
+ buttonRead.Name = "buttonRead";
+ buttonRead.Size = new Size(105, 29);
+ buttonRead.TabIndex = 19;
+ buttonRead.Text = "Получить";
+ buttonRead.UseVisualStyleBackColor = true;
+ buttonRead.Click += buttonRead_Click;
+ //
+ // buttonInsert
+ //
+ buttonInsert.Location = new Point(337, 18);
+ buttonInsert.Name = "buttonInsert";
+ buttonInsert.Size = new Size(105, 29);
+ buttonInsert.TabIndex = 18;
+ buttonInsert.Text = "Создать";
+ buttonInsert.UseVisualStyleBackColor = true;
+ buttonInsert.Click += buttonInsert_Click;
+ //
+ // labelDeleteTime
+ //
+ labelDeleteTime.AutoSize = true;
+ labelDeleteTime.Location = new Point(463, 119);
+ labelDeleteTime.Name = "labelDeleteTime";
+ labelDeleteTime.Size = new Size(255, 20);
+ labelDeleteTime.TabIndex = 23;
+ labelDeleteTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // labelReadTime
+ //
+ labelReadTime.AutoSize = true;
+ labelReadTime.Location = new Point(463, 72);
+ labelReadTime.Name = "labelReadTime";
+ labelReadTime.Size = new Size(255, 20);
+ labelReadTime.TabIndex = 22;
+ labelReadTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // labelInsertTime
+ //
+ labelInsertTime.AutoSize = true;
+ labelInsertTime.Location = new Point(463, 23);
+ labelInsertTime.Name = "labelInsertTime";
+ labelInsertTime.Size = new Size(255, 20);
+ labelInsertTime.TabIndex = 21;
+ labelInsertTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // FormStopsTests
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(734, 162);
+ Controls.Add(labelDeleteTime);
+ Controls.Add(labelReadTime);
+ Controls.Add(labelInsertTime);
+ Controls.Add(buttonDelete);
+ Controls.Add(buttonRead);
+ Controls.Add(buttonInsert);
+ Controls.Add(labelEntities3);
+ Controls.Add(labelEntities2);
+ Controls.Add(labelEntities1);
+ Controls.Add(numericUpDownDelete);
+ Controls.Add(numericUpDownRead);
+ Controls.Add(numericUpDownInsert);
+ Controls.Add(labelDelete);
+ Controls.Add(labelRead);
+ Controls.Add(labelInsert);
+ Name = "FormStopsTests";
+ Text = " Тесты для сущности \"Остановка\"";
+ ((System.ComponentModel.ISupportInitialize)numericUpDownDelete).EndInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownRead).EndInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownInsert).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Label labelDelete;
+ private Label labelRead;
+ private Label labelInsert;
+ private NumericUpDown numericUpDownDelete;
+ private NumericUpDown numericUpDownRead;
+ private NumericUpDown numericUpDownInsert;
+ private Label labelEntities3;
+ private Label labelEntities2;
+ private Label labelEntities1;
+ private Button buttonDelete;
+ private Button buttonRead;
+ private Button buttonInsert;
+ private Label labelDeleteTime;
+ private Label labelReadTime;
+ private Label labelInsertTime;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormStopsTests.cs b/RouteDirectory/RouteDirectoryForms/FormStopsTests.cs
new file mode 100644
index 0000000..fc2d5ad
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStopsTests.cs
@@ -0,0 +1,142 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using static System.Windows.Forms.VisualStyles.VisualStyleElement.TaskbarClock;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма с тестами для сущности "Остановка"
+ ///
+ public partial class FormStopsTests : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика
+ ///
+ private readonly IStopLogic _stopLogic;
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ ///
+ public FormStopsTests(ILogger logger, IStopLogic stopLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _stopLogic = stopLogic;
+
+ numericUpDownInsert.Maximum = 10000;
+ numericUpDownRead.Maximum = 10000;
+ numericUpDownDelete.Maximum = 10000;
+ }
+
+ ///
+ /// Кнопка "Создать"
+ ///
+ ///
+ ///
+ private void buttonInsert_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownInsert.Value);
+ _logger.LogInformation("StopInsertTest. Count: {Count}", entitiesCount);
+ try
+ {
+ double time = 0;
+ var stopwatch = new Stopwatch();
+ for (int i = 1; i <= entitiesCount; i++)
+ {
+ var model = new StopBindingModel
+ {
+ Id = 0,
+ Name = $"Остановка {i}",
+ };
+
+ stopwatch.Restart();
+ var operationResult = _stopLogic.Create(model);
+ if (!operationResult)
+ {
+ throw new Exception("Ошибка при сохранении сущности 'Остановка'. Дополнительная информация в логах.");
+ }
+ stopwatch.Stop();
+ time += stopwatch.ElapsedMilliseconds;
+ }
+ labelInsertTime.Text = $"Total time: {Convert.ToInt32(time)} ms / Average time: {Convert.ToInt32(time / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "StopInsertTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Получить"
+ ///
+ ///
+ ///
+ private void buttonRead_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownRead.Value);
+ _logger.LogInformation("StopReadTest. Count: {Count}", entitiesCount);
+ try
+ {
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
+ _stopLogic.ReadList(entitiesCount);
+ stopwatch.Stop();
+ labelReadTime.Text = $"Total time: {Convert.ToInt32(stopwatch.ElapsedMilliseconds)} ms / Average time: {Convert.ToInt32(stopwatch.ElapsedMilliseconds / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "StopReadTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Удалить"
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownDelete.Value);
+ _logger.LogInformation("StopDeleteTest. Count: {Count}", entitiesCount);
+ try
+ {
+ double time = 0;
+ var stopwatch = new Stopwatch();
+ for (int i = 1; i <= entitiesCount; i++)
+ {
+ stopwatch.Restart();
+ _stopLogic.Delete();
+ stopwatch.Stop();
+ time += stopwatch.ElapsedMilliseconds;
+ }
+ labelDeleteTime.Text = $"Total time: {Convert.ToInt32(time)} ms / Average time: {Convert.ToInt32(time / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "StopDeleteTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormStopsTests.resx b/RouteDirectory/RouteDirectoryForms/FormStopsTests.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormStopsTests.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransport.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormTransport.Designer.cs
new file mode 100644
index 0000000..e1221ff
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransport.Designer.cs
@@ -0,0 +1,119 @@
+namespace RouteDirectoryView
+{
+ partial class FormTransport
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ label1 = new Label();
+ label3 = new Label();
+ comboBoxType = new ComboBox();
+ textBoxCapacity = new TextBox();
+ buttonSave = new Button();
+ buttonCancel = new Button();
+ SuspendLayout();
+ //
+ // label1
+ //
+ label1.AutoSize = true;
+ label1.Location = new Point(12, 24);
+ label1.Name = "label1";
+ label1.Size = new Size(38, 20);
+ label1.TabIndex = 0;
+ label1.Text = "Тип:";
+ //
+ // label3
+ //
+ label3.AutoSize = true;
+ label3.Location = new Point(12, 65);
+ label3.Name = "label3";
+ label3.Size = new Size(103, 20);
+ label3.TabIndex = 2;
+ label3.Text = "Вместимость:";
+ //
+ // comboBoxType
+ //
+ comboBoxType.FormattingEnabled = true;
+ comboBoxType.Location = new Point(129, 21);
+ comboBoxType.Name = "comboBoxType";
+ comboBoxType.Size = new Size(232, 28);
+ comboBoxType.TabIndex = 4;
+ //
+ // textBoxCapacity
+ //
+ textBoxCapacity.Location = new Point(129, 65);
+ textBoxCapacity.Name = "textBoxCapacity";
+ textBoxCapacity.Size = new Size(232, 27);
+ textBoxCapacity.TabIndex = 6;
+ //
+ // buttonSave
+ //
+ buttonSave.Location = new Point(156, 109);
+ buttonSave.Name = "buttonSave";
+ buttonSave.Size = new Size(94, 29);
+ buttonSave.TabIndex = 8;
+ buttonSave.Text = "Сохранить";
+ buttonSave.UseVisualStyleBackColor = true;
+ buttonSave.Click += buttonSave_Click;
+ //
+ // buttonCancel
+ //
+ buttonCancel.Location = new Point(267, 109);
+ buttonCancel.Name = "buttonCancel";
+ buttonCancel.Size = new Size(94, 29);
+ buttonCancel.TabIndex = 9;
+ buttonCancel.Text = "Отмена";
+ buttonCancel.UseVisualStyleBackColor = true;
+ buttonCancel.Click += buttonCancel_Click;
+ //
+ // FormTransport
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(389, 152);
+ Controls.Add(buttonCancel);
+ Controls.Add(buttonSave);
+ Controls.Add(textBoxCapacity);
+ Controls.Add(comboBoxType);
+ Controls.Add(label3);
+ Controls.Add(label1);
+ Name = "FormTransport";
+ Text = "Транспорт";
+ Load += FormTransport_Load;
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Label label1;
+ private Label label3;
+ private ComboBox comboBoxType;
+ private TextBox textBoxCapacity;
+ private Button buttonSave;
+ private Button buttonCancel;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransport.cs b/RouteDirectory/RouteDirectoryForms/FormTransport.cs
new file mode 100644
index 0000000..5d8cb88
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransport.cs
@@ -0,0 +1,151 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using RouteDirectoryContracts.SearchModels;
+using RouteDirectoryDataModels.Enums;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма для создания/редактирования транспорта
+ ///
+ public partial class FormTransport : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика для транспорта
+ ///
+ private readonly ITransportTypeLogic _transportLogic;
+
+ ///
+ /// Идентификатор
+ ///
+ private int? _id;
+
+ ///
+ /// Идентификатор
+ ///
+ public int Id { set { _id = value; } }
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ ///
+ ///
+ public FormTransport(ILogger logger, ITransportTypeLogic transportLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _transportLogic = transportLogic;
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ ///
+ ///
+ private void FormTransport_Load(object sender, EventArgs e)
+ {
+ // Загрузка типов транспорта для ComboBoxType
+ foreach (TransportType type in Enum.GetValues(typeof(TransportType)))
+ {
+ comboBoxType.Items.Add(type);
+ }
+
+ if (!_id.HasValue)
+ {
+ return;
+ }
+
+ try
+ {
+ // Заполнение полей
+ _logger.LogInformation("Получение сущности 'Транспорт'");
+ var view = _transportLogic.ReadElement(new TransportTypeSearchModel
+ {
+ Id = _id.Value
+ });
+ if (view != null)
+ {
+ textBoxCapacity.Text = view.Capacity.ToString();
+ comboBoxType.SelectedItem = view.Type;
+ }
+ }
+ catch (Exception ex1)
+ {
+ MessageBox.Show(ex1.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Сохранить"
+ ///
+ ///
+ ///
+ private void buttonSave_Click(object sender, EventArgs e)
+ {
+ if (comboBoxType.SelectedIndex == -1)
+ {
+ MessageBox.Show("Выберите тип транспорта", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+ if (string.IsNullOrEmpty(textBoxCapacity.Text))
+ {
+ MessageBox.Show("Заполните вместимость", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ return;
+ }
+
+ _logger.LogInformation("Сохранение сущности 'Транспорт'");
+ try
+ {
+ var model = new TransportTypeBindingModel
+ {
+ Id = _id ?? 0,
+ Type = (TransportType)comboBoxType.SelectedItem,
+ Capacity = textBoxCapacity.Text
+ };
+
+ var operationResult = _id.HasValue ? _transportLogic.Update(model) : _transportLogic.Create(model);
+ if (!operationResult)
+ {
+ throw new Exception("Ошибка при сохранении сущности 'Транспорт'. Дополнительная информация в логах.");
+ }
+
+ MessageBox.Show("Сохранение сущности 'Транспорт' прошло успешно", "Сообщение", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка сохранения сущности 'Транспорт'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Отмена"
+ ///
+ ///
+ ///
+ private void buttonCancel_Click(object sender, EventArgs e)
+ {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransport.resx b/RouteDirectory/RouteDirectoryForms/FormTransport.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransport.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransportTests.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormTransportTests.Designer.cs
new file mode 100644
index 0000000..cffdca7
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransportTests.Designer.cs
@@ -0,0 +1,227 @@
+namespace RouteDirectoryForms
+{
+ partial class FormTransportTests
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ labelDeleteTime = new Label();
+ labelReadTime = new Label();
+ labelInsertTime = new Label();
+ buttonDelete = new Button();
+ buttonRead = new Button();
+ buttonInsert = new Button();
+ labelEntities3 = new Label();
+ labelEntities2 = new Label();
+ labelEntities1 = new Label();
+ numericUpDownDelete = new NumericUpDown();
+ numericUpDownRead = new NumericUpDown();
+ numericUpDownInsert = new NumericUpDown();
+ labelDelete = new Label();
+ labelRead = new Label();
+ labelInsert = new Label();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownDelete).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownRead).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownInsert).BeginInit();
+ SuspendLayout();
+ //
+ // labelDeleteTime
+ //
+ labelDeleteTime.AutoSize = true;
+ labelDeleteTime.Location = new Point(483, 126);
+ labelDeleteTime.Name = "labelDeleteTime";
+ labelDeleteTime.Size = new Size(255, 20);
+ labelDeleteTime.TabIndex = 44;
+ labelDeleteTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // labelReadTime
+ //
+ labelReadTime.AutoSize = true;
+ labelReadTime.Location = new Point(483, 79);
+ labelReadTime.Name = "labelReadTime";
+ labelReadTime.Size = new Size(255, 20);
+ labelReadTime.TabIndex = 43;
+ labelReadTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // labelInsertTime
+ //
+ labelInsertTime.AutoSize = true;
+ labelInsertTime.Location = new Point(483, 30);
+ labelInsertTime.Name = "labelInsertTime";
+ labelInsertTime.Size = new Size(255, 20);
+ labelInsertTime.TabIndex = 42;
+ labelInsertTime.Text = "Total time: 0 ms / Average time: 0 ms";
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(346, 121);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(105, 29);
+ buttonDelete.TabIndex = 41;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ //
+ // buttonRead
+ //
+ buttonRead.Location = new Point(346, 75);
+ buttonRead.Name = "buttonRead";
+ buttonRead.Size = new Size(105, 29);
+ buttonRead.TabIndex = 40;
+ buttonRead.Text = "Получить";
+ buttonRead.UseVisualStyleBackColor = true;
+ //
+ // buttonInsert
+ //
+ buttonInsert.Location = new Point(346, 24);
+ buttonInsert.Name = "buttonInsert";
+ buttonInsert.Size = new Size(105, 29);
+ buttonInsert.TabIndex = 39;
+ buttonInsert.Text = "Создать";
+ buttonInsert.UseVisualStyleBackColor = true;
+ //
+ // labelEntities3
+ //
+ labelEntities3.AutoSize = true;
+ labelEntities3.Location = new Point(248, 127);
+ labelEntities3.Name = "labelEntities3";
+ labelEntities3.Size = new Size(83, 20);
+ labelEntities3.TabIndex = 38;
+ labelEntities3.Text = "сущностей";
+ //
+ // labelEntities2
+ //
+ labelEntities2.AutoSize = true;
+ labelEntities2.Location = new Point(248, 75);
+ labelEntities2.Name = "labelEntities2";
+ labelEntities2.Size = new Size(83, 20);
+ labelEntities2.TabIndex = 37;
+ labelEntities2.Text = "сущностей";
+ //
+ // labelEntities1
+ //
+ labelEntities1.AutoSize = true;
+ labelEntities1.Location = new Point(248, 26);
+ labelEntities1.Name = "labelEntities1";
+ labelEntities1.Size = new Size(83, 20);
+ labelEntities1.TabIndex = 36;
+ labelEntities1.Text = "сущностей";
+ //
+ // numericUpDownDelete
+ //
+ numericUpDownDelete.Location = new Point(110, 123);
+ numericUpDownDelete.Name = "numericUpDownDelete";
+ numericUpDownDelete.Size = new Size(114, 27);
+ numericUpDownDelete.TabIndex = 35;
+ //
+ // numericUpDownRead
+ //
+ numericUpDownRead.Location = new Point(110, 73);
+ numericUpDownRead.Name = "numericUpDownRead";
+ numericUpDownRead.Size = new Size(114, 27);
+ numericUpDownRead.TabIndex = 34;
+ //
+ // numericUpDownInsert
+ //
+ numericUpDownInsert.Location = new Point(110, 24);
+ numericUpDownInsert.Name = "numericUpDownInsert";
+ numericUpDownInsert.Size = new Size(114, 27);
+ numericUpDownInsert.TabIndex = 33;
+ //
+ // labelDelete
+ //
+ labelDelete.AutoSize = true;
+ labelDelete.Location = new Point(18, 125);
+ labelDelete.Name = "labelDelete";
+ labelDelete.Size = new Size(65, 20);
+ labelDelete.TabIndex = 32;
+ labelDelete.Text = "Удалить";
+ //
+ // labelRead
+ //
+ labelRead.AutoSize = true;
+ labelRead.Location = new Point(18, 73);
+ labelRead.Name = "labelRead";
+ labelRead.Size = new Size(75, 20);
+ labelRead.TabIndex = 31;
+ labelRead.Text = "Получить";
+ //
+ // labelInsert
+ //
+ labelInsert.AutoSize = true;
+ labelInsert.Location = new Point(18, 26);
+ labelInsert.Name = "labelInsert";
+ labelInsert.Size = new Size(64, 20);
+ labelInsert.TabIndex = 30;
+ labelInsert.Text = "Создать";
+ //
+ // FormTransportTests
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(765, 170);
+ Controls.Add(labelDeleteTime);
+ Controls.Add(labelReadTime);
+ Controls.Add(labelInsertTime);
+ Controls.Add(buttonDelete);
+ Controls.Add(buttonRead);
+ Controls.Add(buttonInsert);
+ Controls.Add(labelEntities3);
+ Controls.Add(labelEntities2);
+ Controls.Add(labelEntities1);
+ Controls.Add(numericUpDownDelete);
+ Controls.Add(numericUpDownRead);
+ Controls.Add(numericUpDownInsert);
+ Controls.Add(labelDelete);
+ Controls.Add(labelRead);
+ Controls.Add(labelInsert);
+ Name = "FormTransportTests";
+ Text = " Тесты для сущности \"Маршрут\"";
+ ((System.ComponentModel.ISupportInitialize)numericUpDownDelete).EndInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownRead).EndInit();
+ ((System.ComponentModel.ISupportInitialize)numericUpDownInsert).EndInit();
+ ResumeLayout(false);
+ PerformLayout();
+ }
+
+ #endregion
+
+ private Label labelDeleteTime;
+ private Label labelReadTime;
+ private Label labelInsertTime;
+ private Button buttonDelete;
+ private Button buttonRead;
+ private Button buttonInsert;
+ private Label labelEntities3;
+ private Label labelEntities2;
+ private Label labelEntities1;
+ private NumericUpDown numericUpDownDelete;
+ private NumericUpDown numericUpDownRead;
+ private NumericUpDown numericUpDownInsert;
+ private Label labelDelete;
+ private Label labelRead;
+ private Label labelInsert;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransportTests.cs b/RouteDirectory/RouteDirectoryForms/FormTransportTests.cs
new file mode 100644
index 0000000..d8603d4
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransportTests.cs
@@ -0,0 +1,140 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using RouteDirectoryDataModels.Enums;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Diagnostics;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryForms
+{
+ public partial class FormTransportTests : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика для транспорта
+ ///
+ private readonly ITransportTypeLogic _transportLogic;
+
+ ///
+ /// Конструктор
+ ///
+ ///
+ ///
+ ///
+ public FormTransportTests(ILogger logger, ITransportTypeLogic transportLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _transportLogic = transportLogic;
+
+ numericUpDownInsert.Maximum = 10000;
+ numericUpDownRead.Maximum = 10000;
+ numericUpDownDelete.Maximum = 10000;
+ }
+
+ ///
+ /// Кнопка "Создать"
+ ///
+ ///
+ ///
+ private void buttonInsert_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownInsert.Value);
+ _logger.LogInformation("TransportInsertTest. Count: {Count}", entitiesCount);
+ try
+ {
+ double time = 0;
+ var stopwatch = new Stopwatch();
+ for (int i = 1; i <= entitiesCount; i++)
+ {
+ var model = new TransportTypeBindingModel
+ {
+ Id = 0,
+ Type = TransportType.Маршрутка,
+ Capacity = i.ToString(),
+ };
+
+ stopwatch.Restart();
+ var operationResult = _transportLogic.Create(model);
+ if (!operationResult)
+ {
+ throw new Exception("Ошибка при сохранении сущности 'Транспорт'. Дополнительная информация в логах.");
+ }
+ stopwatch.Stop();
+ time += stopwatch.ElapsedMilliseconds;
+ }
+ labelInsertTime.Text = $"Total time: {Convert.ToInt32(time)} ms / Average time: {Convert.ToInt32(time / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "TransportInsertTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Получить"
+ ///
+ ///
+ ///
+ private void buttonRead_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownRead.Value);
+ _logger.LogInformation("TransportReadTest. Count: {Count}", entitiesCount);
+ try
+ {
+ var stopwatch = new Stopwatch();
+ stopwatch.Start();
+ _transportLogic.ReadList(entitiesCount);
+ stopwatch.Stop();
+ labelReadTime.Text = $"Total time: {Convert.ToInt32(stopwatch.ElapsedMilliseconds)} ms / Average time: {Convert.ToInt32(stopwatch.ElapsedMilliseconds / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "TransportReadTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+
+ ///
+ /// Кнопка "Удалить"
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ int entitiesCount = Convert.ToInt32(numericUpDownDelete.Value);
+ _logger.LogInformation("TransportDeleteTest. Count: {Count}", entitiesCount);
+ try
+ {
+ double time = 0;
+ var stopwatch = new Stopwatch();
+ for (int i = 1; i <= entitiesCount; i++)
+ {
+ stopwatch.Restart();
+ _transportLogic.Delete();
+ stopwatch.Stop();
+ time += stopwatch.ElapsedMilliseconds;
+ }
+ labelDeleteTime.Text = $"Total time: {Convert.ToInt32(time)} ms / Average time: {Convert.ToInt32(time / entitiesCount)} ms";
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "TransportDeleteTest. Test failed");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransportTests.resx b/RouteDirectory/RouteDirectoryForms/FormTransportTests.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransportTests.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransports.Designer.cs b/RouteDirectory/RouteDirectoryForms/FormTransports.Designer.cs
new file mode 100644
index 0000000..f157d11
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransports.Designer.cs
@@ -0,0 +1,114 @@
+namespace RouteDirectoryView
+{
+ partial class FormTransports
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent()
+ {
+ buttonRefresh = new Button();
+ buttonDelete = new Button();
+ buttonUpdate = new Button();
+ buttonCreate = new Button();
+ dataGridView = new DataGridView();
+ ((System.ComponentModel.ISupportInitialize)dataGridView).BeginInit();
+ SuspendLayout();
+ //
+ // buttonRefresh
+ //
+ buttonRefresh.Location = new Point(685, 173);
+ buttonRefresh.Name = "buttonRefresh";
+ buttonRefresh.Size = new Size(94, 29);
+ buttonRefresh.TabIndex = 9;
+ buttonRefresh.Text = "Обновить";
+ buttonRefresh.UseVisualStyleBackColor = true;
+ buttonRefresh.Click += buttonRefresh_Click;
+ //
+ // buttonDelete
+ //
+ buttonDelete.Location = new Point(685, 123);
+ buttonDelete.Name = "buttonDelete";
+ buttonDelete.Size = new Size(94, 29);
+ buttonDelete.TabIndex = 8;
+ buttonDelete.Text = "Удалить";
+ buttonDelete.UseVisualStyleBackColor = true;
+ buttonDelete.Click += buttonDelete_Click;
+ //
+ // buttonUpdate
+ //
+ buttonUpdate.Location = new Point(685, 72);
+ buttonUpdate.Name = "buttonUpdate";
+ buttonUpdate.Size = new Size(94, 29);
+ buttonUpdate.TabIndex = 7;
+ buttonUpdate.Text = "Изменить";
+ buttonUpdate.UseVisualStyleBackColor = true;
+ buttonUpdate.Click += buttonUpdate_Click;
+ //
+ // buttonCreate
+ //
+ buttonCreate.Location = new Point(685, 21);
+ buttonCreate.Name = "buttonCreate";
+ buttonCreate.Size = new Size(94, 29);
+ buttonCreate.TabIndex = 6;
+ buttonCreate.Text = "Создать";
+ buttonCreate.UseVisualStyleBackColor = true;
+ buttonCreate.Click += buttonCreate_Click;
+ //
+ // dataGridView
+ //
+ dataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ dataGridView.Location = new Point(1, 1);
+ dataGridView.Name = "dataGridView";
+ dataGridView.RowHeadersWidth = 51;
+ dataGridView.RowTemplate.Height = 29;
+ dataGridView.Size = new Size(665, 447);
+ dataGridView.TabIndex = 5;
+ //
+ // FormTransports
+ //
+ AutoScaleDimensions = new SizeF(8F, 20F);
+ AutoScaleMode = AutoScaleMode.Font;
+ ClientSize = new Size(800, 450);
+ Controls.Add(buttonRefresh);
+ Controls.Add(buttonDelete);
+ Controls.Add(buttonUpdate);
+ Controls.Add(buttonCreate);
+ Controls.Add(dataGridView);
+ Name = "FormTransports";
+ Text = "Транспорт";
+ Load += FormTransports_Load;
+ ((System.ComponentModel.ISupportInitialize)dataGridView).EndInit();
+ ResumeLayout(false);
+ }
+
+ #endregion
+
+ private Button buttonRefresh;
+ private Button buttonDelete;
+ private Button buttonUpdate;
+ private Button buttonCreate;
+ private DataGridView dataGridView;
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransports.cs b/RouteDirectory/RouteDirectoryForms/FormTransports.cs
new file mode 100644
index 0000000..2130b55
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransports.cs
@@ -0,0 +1,154 @@
+using Microsoft.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BindingModels;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace RouteDirectoryView
+{
+ ///
+ /// Форма для вывода списка транспорта
+ ///
+ public partial class FormTransports : Form
+ {
+ ///
+ /// Логгер
+ ///
+ private readonly ILogger _logger;
+
+ ///
+ /// Бизнес-логика
+ ///
+ private readonly ITransportTypeLogic _transportlogic;
+
+ ///
+ /// Конструктор
+ ///
+ public FormTransports(ILogger logger, ITransportTypeLogic transportLogic)
+ {
+ InitializeComponent();
+ _logger = logger;
+ _transportlogic = transportLogic;
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ ///
+ ///
+ private void FormTransports_Load(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Кнопка "Создать"
+ ///
+ ///
+ ///
+ private void buttonCreate_Click(object sender, EventArgs e)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormTransport));
+ if (service is FormTransport form)
+ {
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ LoadData();
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Изменить"
+ ///
+ ///
+ ///
+ private void buttonUpdate_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ var service = Program.ServiceProvider?.GetService(typeof(FormTransport));
+ if (service is FormTransport form)
+ {
+ form.Id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
+ if (form.ShowDialog() == DialogResult.OK)
+ {
+ LoadData();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Удалить"
+ ///
+ ///
+ ///
+ private void buttonDelete_Click(object sender, EventArgs e)
+ {
+ if (dataGridView.SelectedRows.Count == 1)
+ {
+ if (MessageBox.Show("Удалить запись?", "Вопрос", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
+ {
+ int id = Convert.ToInt32(dataGridView.SelectedRows[0].Cells["Id"].Value);
+ _logger.LogInformation("Удаление сущности 'Транспорт'");
+
+ try
+ {
+ if (!_transportlogic.Delete(new TransportTypeBindingModel { Id = id }))
+ {
+ throw new Exception("Ошибка при удалении сущности 'Транспорт'. Дополнительная информация в логах.");
+ }
+ LoadData();
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка удаления сущности 'Транспорт'");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Кнопка "Обновить"
+ ///
+ ///
+ ///
+ private void buttonRefresh_Click(object sender, EventArgs e)
+ {
+ LoadData();
+ }
+
+ ///
+ /// Загрузка данных
+ ///
+ private void LoadData()
+ {
+ try
+ {
+ var list = _transportlogic.ReadList(null);
+ if (list != null)
+ {
+ dataGridView.DataSource = list;
+ dataGridView.Columns["Id"].Visible = false;
+ dataGridView.Columns["Capacity"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
+ }
+ _logger.LogInformation("Загрузка списка транспорта");
+ }
+ catch (Exception ex)
+ {
+ _logger.LogError(ex, "Ошибка загрузки списка транспорта");
+ MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/RouteDirectory/RouteDirectoryForms/FormTransports.resx b/RouteDirectory/RouteDirectoryForms/FormTransports.resx
new file mode 100644
index 0000000..af32865
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/FormTransports.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/Program.cs b/RouteDirectory/RouteDirectoryForms/Program.cs
new file mode 100644
index 0000000..0e1fddb
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/Program.cs
@@ -0,0 +1,84 @@
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using NLog.Extensions.Logging;
+using RouteDirectoryBusinessLogics.BusinessLogics;
+using RouteDirectoryContracts.BusinessLogicsContracts;
+using RouteDirectoryContracts.StoragesContracts;
+using RouteDirectoryDatabaseImplement.Implements;
+using RouteDirectoryForms;
+using System;
+
+namespace RouteDirectoryView
+{
+ internal static class Program
+ {
+ ///
+ /// IoC-контейнер
+ ///
+ private static ServiceProvider? _serviceProvider;
+ public static ServiceProvider? ServiceProvider => _serviceProvider;
+
+ ///
+ /// The main entry point for the application.
+ ///
+ [STAThread]
+ static void Main()
+ {
+ // To customize application configuration such as set high DPI settings or default font,
+ // see https://aka.ms/applicationconfiguration.
+ ApplicationConfiguration.Initialize();
+
+ var services = new ServiceCollection();
+ ConfigureServices(services);
+ _serviceProvider = services.BuildServiceProvider();
+
+ Application.Run(_serviceProvider.GetRequiredService());
+ }
+
+ ///
+ /// Конфигурация сервисов
+ ///
+ ///
+ private static void ConfigureServices(ServiceCollection services)
+ {
+ // Логгер
+ services.AddLogging(option =>
+ {
+ option.SetMinimumLevel(LogLevel.Information);
+ option.AddNLog("nlog.config");
+ });
+
+ // IoC-контейнер, хранилища
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+
+ // IoC-контейнер, бизнес-логика
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+
+ // IoC-контейнер, основные формы
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+
+ // IoC-контейнер, формы для тестов
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+ services.AddTransient();
+
+ // Запись DateTime Kind=Local в БД
+ AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
+ }
+ }
+}
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/RouteDirectoryView.csproj b/RouteDirectory/RouteDirectoryForms/RouteDirectoryView.csproj
new file mode 100644
index 0000000..40a0177
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/RouteDirectoryView.csproj
@@ -0,0 +1,60 @@
+
+
+
+ WinExe
+ net6.0-windows
+ enable
+ true
+ enable
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form
+
+
+ Form
+
+
+ Form
+
+
+ Form
+
+
+ Form
+
+
+ Form
+
+
+ Form
+
+
+ Form
+
+
+ Form
+
+
+
+
\ No newline at end of file
diff --git a/RouteDirectory/RouteDirectoryForms/nlog.config b/RouteDirectory/RouteDirectoryForms/nlog.config
new file mode 100644
index 0000000..bf280eb
--- /dev/null
+++ b/RouteDirectory/RouteDirectoryForms/nlog.config
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file