осталось подключиться к бд.......

This commit is contained in:
kamilia 2024-05-14 23:23:27 +04:00
parent f12b514584
commit 843569550f
49 changed files with 6695 additions and 15 deletions

View File

@ -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

View File

@ -0,0 +1,201 @@
// <auto-generated />
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
{
/// <inheritdoc />
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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Fare")
.HasColumnType("int");
b.Property<string>("RouteNumber")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("TransportId")
.HasColumnType("int");
b.Property<int>("TransportTypeId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TransportTypeId");
b.ToTable("Routes");
});
modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.RouteStop", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Number")
.HasColumnType("int");
b.Property<int>("RouteId")
.HasColumnType("int");
b.Property<int>("StopId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("RouteId");
b.HasIndex("StopId");
b.ToTable("RouteStops");
});
modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Schedule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("EndTime")
.HasColumnType("datetime2");
b.Property<int>("RouteId")
.HasColumnType("int");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.Property<DateTime>("TrafficInterval")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("RouteId");
b.ToTable("Schedules");
});
modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Stop", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Number")
.HasColumnType("int");
b.Property<string>("Street")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Stops");
});
modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.TransportType", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Capacity")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("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
}
}
}

View File

@ -0,0 +1,154 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace RouteDirectoryDatabaseImplement.Migrations
{
/// <inheritdoc />
public partial class InitMigration : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Stops",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(max)", nullable: false),
Street = table.Column<string>(type: "nvarchar(max)", nullable: false),
Number = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Stops", x => x.Id);
});
migrationBuilder.CreateTable(
name: "TransportTypes",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Type = table.Column<int>(type: "int", nullable: false),
Capacity = table.Column<string>(type: "nvarchar(max)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TransportTypes", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Routes",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RouteNumber = table.Column<string>(type: "nvarchar(max)", nullable: false),
Fare = table.Column<int>(type: "int", nullable: false),
TransportId = table.Column<int>(type: "int", nullable: false),
TransportTypeId = table.Column<int>(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<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
RouteId = table.Column<int>(type: "int", nullable: false),
StopId = table.Column<int>(type: "int", nullable: false),
Number = table.Column<int>(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<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
StartTime = table.Column<DateTime>(type: "datetime2", nullable: false),
EndTime = table.Column<DateTime>(type: "datetime2", nullable: false),
TrafficInterval = table.Column<DateTime>(type: "datetime2", nullable: false),
RouteId = table.Column<int>(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");
}
/// <inheritdoc />
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");
}
}
}

View File

@ -0,0 +1,198 @@
// <auto-generated />
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<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Fare")
.HasColumnType("int");
b.Property<string>("RouteNumber")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("TransportId")
.HasColumnType("int");
b.Property<int>("TransportTypeId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("TransportTypeId");
b.ToTable("Routes");
});
modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.RouteStop", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<int>("Number")
.HasColumnType("int");
b.Property<int>("RouteId")
.HasColumnType("int");
b.Property<int>("StopId")
.HasColumnType("int");
b.HasKey("Id");
b.HasIndex("RouteId");
b.HasIndex("StopId");
b.ToTable("RouteStops");
});
modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Schedule", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<DateTime>("EndTime")
.HasColumnType("datetime2");
b.Property<int>("RouteId")
.HasColumnType("int");
b.Property<DateTime>("StartTime")
.HasColumnType("datetime2");
b.Property<DateTime>("TrafficInterval")
.HasColumnType("datetime2");
b.HasKey("Id");
b.HasIndex("RouteId");
b.ToTable("Schedules");
});
modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.Stop", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Name")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("Number")
.HasColumnType("int");
b.Property<string>("Street")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.HasKey("Id");
b.ToTable("Stops");
});
modelBuilder.Entity("RouteDirectoryDatabaseImplement.Models.TransportType", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
b.Property<string>("Capacity")
.IsRequired()
.HasColumnType("nvarchar(max)");
b.Property<int>("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
}
}
}

View File

@ -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;
}
/// <summary>
@ -104,8 +98,6 @@ namespace RouteDirectoryDatabaseImplement.Models
{
Id = Id,
Name = Name,
Street = Street,
Number = Number
};
}
}

View File

@ -13,6 +13,7 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.11" />
</ItemGroup>
<ItemGroup>

View File

@ -8,13 +8,22 @@ using System.Threading.Tasks;
namespace RouteDirectoryDatabaseImplement
{
public class RouteDirectoryDatabase : DbContext
public class RouteGuideDatabase : DbContext
{
/// <summary>
/// Параметры подключения к базе данных
/// </summary>
private string _dbConnectionString = "Host=192.168.56.102;Port=5432;Database=postgres;Username=postgres;Password=зщыепкуы";
/// <summary>
/// Подключение к базе данных
/// </summary>
/// <param name="optionsBuilder"></param>
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);
}

View File

@ -0,0 +1,213 @@
namespace RouteDirectoryView
{
partial class FormMain
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для расписаний
/// </summary>
private readonly IScheduleLogic _schedulelogic;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="scheduleLogic"></param>
public FormMain(ILogger<FormMain> logger, IScheduleLogic scheduleLogic)
{
InitializeComponent();
_logger = logger;
_schedulelogic = scheduleLogic;
}
/// <summary>
/// Загрузка данных
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormMain_Load(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Форма для вывода списка транспорта
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TransportToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormTransports));
if (service is FormTransports form)
{
form.ShowDialog();
}
}
/// <summary>
/// Форма для вывода списка маршрутов
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void RoutesToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormRoutes));
if (service is FormRoutes form)
{
form.ShowDialog();
}
}
/// <summary>
/// Форма для вывода списка остановок
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StopsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormStops));
if (service is FormStops form)
{
form.ShowDialog();
}
}
/// <summary>
/// Форма для тестов сущности "Транспорт"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void TransportTestsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormTransportTests));
if (service is FormTransportTests form)
{
form.ShowDialog();
}
}
/// <summary>
/// Форма для тестов сущности "Маршрут"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void RoutesTestsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormRoutesTests));
if (service is FormRoutesTests form)
{
form.ShowDialog();
}
}
/// <summary>
/// Форма для тестов сущности "Остановка"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void StopsTestsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormStopsTests));
if (service is FormStopsTests form)
{
form.ShowDialog();
}
}
/// <summary>
/// Форма для тестов сущности "Расписание"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SchedulesTestsToolStripMenuItem_Click(object sender, EventArgs e)
{
var service = Program.ServiceProvider?.GetService(typeof(FormSchedulesTests));
if (service is FormSchedulesTests form)
{
form.ShowDialog();
}
}
/// <summary>
/// Кнопка "Создать"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
/// <summary>
/// Кнопка "Изменить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
}
/// <summary>
/// Кнопка "Обновить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonRefresh_Click(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Загрузка данных
/// </summary>
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);
}
}
}
}

View File

@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@ -0,0 +1,227 @@
namespace RouteDirectoryView
{
partial class FormRoute
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма для создания/редактирования маршрутов
/// </summary>
public partial class FormRoute : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика маршрутов
/// </summary>
private readonly IRouteLogic _routeLogic;
/// <summary>
/// Бизнес-логика транспорта
/// </summary>
private readonly ITransportTypeLogic _transportLogic;
/// <summary>
/// Идентификатор
/// </summary>
private int? _id;
/// <summary>
/// Идентификатор
/// </summary>
public int Id { set { _id = value; } }
/// <summary>
/// Список остановок в маршруте
/// </summary>
private Dictionary<int, (IStopModel, int)> _routeStops;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="routeLogic"></param>
public FormRoute(ILogger<FormRoute> logger, IRouteLogic routeLogic, ITransportTypeLogic transportLogic)
{
InitializeComponent();
_logger = logger;
_routeLogic = routeLogic;
_transportLogic = transportLogic;
_routeStops = new Dictionary<int, (IStopModel, int)>();
}
/// <summary>
/// Загрузка данных
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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<int, (IStopModel, int)>();
LoadData();
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ошибка получения сущности 'Маршрут'");
MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// Кнопка "Добавить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
/// <summary>
/// Кнопка "Изменить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
/// <summary>
/// Кнопка "Обновить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonRefresh_Click(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Кнопка "Сохранить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Отмена"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
/// <summary>
/// Загрузка данных
/// </summary>
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);
}
}
}
}

View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="ColumnId.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumnName.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<metadata name="ColumNumber.UserAddedColumn" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@ -0,0 +1,118 @@
namespace RouteDirectoryView
{
partial class FormRouteStop
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма для привязки остановки к маршруту
/// </summary>
public partial class FormRouteStop : Form
{
/// <summary>
/// Список остановок
/// </summary>
private readonly List<StopViewModel>? _list;
/// <summary>
/// Идентификатор остановки
/// </summary>
public int Id
{
get
{
return Convert.ToInt32(comboBoxStop.SelectedValue);
}
set
{
comboBoxStop.SelectedValue = value;
}
}
/// <summary>
/// Сущность "Остановка"
/// </summary>
public IStopModel? StopModel
{
get
{
if (_list == null)
{
return null;
}
foreach (var elem in _list)
{
if (elem.Id == Id)
{
return elem;
}
}
return null;
}
}
/// <summary>
/// Номер остановки в маршруте
/// </summary>
public int Number
{
get { return Convert.ToInt32(textBoxNumber.Text); }
set { textBoxNumber.Text = value.ToString(); }
}
/// <summary>
/// Конструктор
/// </summary>
/// <param name="stopLogic"></param>
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;
}
}
/// <summary>
/// Кнопка "Сохранить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
/// <summary>
/// Кнопка "Отмена"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,114 @@
namespace RouteDirectoryView
{
partial class FormRoutes
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма для вывода списка маршрутов
/// </summary>
public partial class FormRoutes : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика
/// </summary>
private readonly IRouteLogic _routelogic;
/// <summary>
/// Конструктор
/// </summary>
public FormRoutes(ILogger<FormRoutes> logger, IRouteLogic routeLogic)
{
InitializeComponent();
_logger = logger;
_routelogic = routeLogic;
}
/// <summary>
/// Загрузка данных
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormRoutes_Load(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Кнопка "Создать"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
/// <summary>
/// Кнопка "Изменить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
}
/// <summary>
/// Кнопка "Обновить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonRefresh_Click(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Загрузка данных
/// </summary>
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);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,230 @@
namespace RouteDirectoryView
{
partial class FormRoutesTests
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма с тестами для сущности "Маршрут"
/// </summary>
public partial class FormRoutesTests : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для маршрутов
/// </summary>
private readonly IRouteLogic _routeLogic;
/// <summary>
/// Бизнес-логика для транспорта
/// </summary>
private readonly ITransportTypeLogic _transportLogic;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="routeLogic"></param>
/// <param name="transportLogic"></param>
public FormRoutesTests(ILogger<FormRoutesTests> logger, IRouteLogic routeLogic, ITransportTypeLogic transportLogic)
{
InitializeComponent();
_logger = logger;
_routeLogic = routeLogic;
_transportLogic = transportLogic;
numericUpDownInsert.Maximum = 10000;
numericUpDownRead.Maximum = 10000;
numericUpDownDelete.Maximum = 10000;
}
/// <summary>
/// Кнопка "Создать"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Получить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,163 @@
namespace RouteDirectoryView
{
partial class FormSchedule
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для расписаний
/// </summary>
private readonly IScheduleLogic _scheduleLogic;
/// <summary>
/// Бизнес-логика для маршрутов
/// </summary>
private readonly IRouteLogic _routeLogic;
/// <summary>
/// Идентификатор
/// </summary>
private int? _id;
/// <summary>
/// Идентификатор
/// </summary>
public int Id { set { _id = value; } }
/// <summary>
/// Констурктор
/// </summary>
/// <param name="logger"></param>
/// <param name="scheduleLogic"></param>
/// <param name="routeLogic"></param>
public FormSchedule(ILogger<FormSchedule> logger, IScheduleLogic scheduleLogic, IRouteLogic routeLogic)
{
InitializeComponent();
_logger = logger;
_scheduleLogic = scheduleLogic;
_routeLogic = routeLogic;
}
/// <summary>
/// Загрузка данных
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Сохранить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Отмена"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,232 @@
namespace RouteDirectoryView
{
partial class FormSchedulesTests
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма с тестами для сущности "Расписание"
/// </summary>
public partial class FormSchedulesTests : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для расписания
/// </summary>
private readonly IScheduleLogic _scheduleLogic;
/// <summary>
/// Бизнес-логика для маршрутов
/// </summary>
private readonly IRouteLogic _routeLogic;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="scheduleLogic"></param>
/// <param name="routeLogic"></param>
public FormSchedulesTests(ILogger<FormSchedulesTests> logger, IScheduleLogic scheduleLogic, IRouteLogic routeLogic)
{
InitializeComponent();
_logger = logger;
_scheduleLogic = scheduleLogic;
_routeLogic = routeLogic;
numericUpDownInsert.Maximum = 10000;
numericUpDownRead.Maximum = 10000;
numericUpDownDelete.Maximum = 10000;
}
/// <summary>
/// Кнопка "Создать"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Получить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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)
{
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,96 @@
namespace RouteDirectoryView
{
partial class FormStop
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма для создания/редактирования остановок
/// </summary>
public partial class FormStop : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика
/// </summary>
private readonly IStopLogic _stopLogic;
/// <summary>
/// Идентификатор
/// </summary>
private int? _id;
/// <summary>
/// Идентификатор
/// </summary>
public int Id { set { _id = value; } }
/// <summary>
/// Конструктор
/// </summary>
public FormStop(ILogger<FormStop> logger, IStopLogic stopLogic)
{
InitializeComponent();
_logger = logger;
_stopLogic = stopLogic;
}
/// <summary>
/// Загрузка информации о сущности
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Сохранить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Отмена"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,114 @@
namespace RouteDirectoryView
{
partial class FormStops
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма для вывода списка остановок
/// </summary>
public partial class FormStops : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика
/// </summary>
private readonly IStopLogic _stoplogic;
/// <summary>
/// Конструктор
/// </summary>
public FormStops(ILogger<FormStops> logger, IStopLogic stopLogic)
{
InitializeComponent();
_logger = logger;
_stoplogic = stopLogic;
}
/// <summary>
/// Загрузка данных
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormStops_Load(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Кнопка "Создать"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
/// <summary>
/// Кнопка "Изменить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
}
/// <summary>
/// Кнопка "Обновить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonRefresh_Click(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Загрузка данных
/// </summary>
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);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,230 @@
namespace RouteDirectoryView
{
partial class FormStopsTests
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма с тестами для сущности "Остановка"
/// </summary>
public partial class FormStopsTests : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика
/// </summary>
private readonly IStopLogic _stopLogic;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="stopLogic"></param>
public FormStopsTests(ILogger<FormStopsTests> logger, IStopLogic stopLogic)
{
InitializeComponent();
_logger = logger;
_stopLogic = stopLogic;
numericUpDownInsert.Maximum = 10000;
numericUpDownRead.Maximum = 10000;
numericUpDownDelete.Maximum = 10000;
}
/// <summary>
/// Кнопка "Создать"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Получить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,119 @@
namespace RouteDirectoryView
{
partial class FormTransport
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма для создания/редактирования транспорта
/// </summary>
public partial class FormTransport : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для транспорта
/// </summary>
private readonly ITransportTypeLogic _transportLogic;
/// <summary>
/// Идентификатор
/// </summary>
private int? _id;
/// <summary>
/// Идентификатор
/// </summary>
public int Id { set { _id = value; } }
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="transportLogic"></param>
/// <param name="driverLogic"></param>
public FormTransport(ILogger<FormTransport> logger, ITransportTypeLogic transportLogic)
{
InitializeComponent();
_logger = logger;
_transportLogic = transportLogic;
}
/// <summary>
/// Загрузка данных
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Сохранить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Отмена"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,227 @@
namespace RouteDirectoryForms
{
partial class FormTransportTests
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика для транспорта
/// </summary>
private readonly ITransportTypeLogic _transportLogic;
/// <summary>
/// Конструктор
/// </summary>
/// <param name="logger"></param>
/// <param name="transportLogic"></param>
/// <param name="driverLogic"></param>
public FormTransportTests(ILogger<FormTransportTests> logger, ITransportTypeLogic transportLogic)
{
InitializeComponent();
_logger = logger;
_transportLogic = transportLogic;
numericUpDownInsert.Maximum = 10000;
numericUpDownRead.Maximum = 10000;
numericUpDownDelete.Maximum = 10000;
}
/// <summary>
/// Кнопка "Создать"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Получить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -0,0 +1,114 @@
namespace RouteDirectoryView
{
partial class FormTransports
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

@ -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
{
/// <summary>
/// Форма для вывода списка транспорта
/// </summary>
public partial class FormTransports : Form
{
/// <summary>
/// Логгер
/// </summary>
private readonly ILogger _logger;
/// <summary>
/// Бизнес-логика
/// </summary>
private readonly ITransportTypeLogic _transportlogic;
/// <summary>
/// Конструктор
/// </summary>
public FormTransports(ILogger<FormTransports> logger, ITransportTypeLogic transportLogic)
{
InitializeComponent();
_logger = logger;
_transportlogic = transportLogic;
}
/// <summary>
/// Загрузка данных
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormTransports_Load(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Кнопка "Создать"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
/// <summary>
/// Кнопка "Изменить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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();
}
}
}
}
/// <summary>
/// Кнопка "Удалить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
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);
}
}
}
}
/// <summary>
/// Кнопка "Обновить"
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonRefresh_Click(object sender, EventArgs e)
{
LoadData();
}
/// <summary>
/// Загрузка данных
/// </summary>
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);
}
}
}
}

View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -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
{
/// <summary>
/// IoC-контейнер
/// </summary>
private static ServiceProvider? _serviceProvider;
public static ServiceProvider? ServiceProvider => _serviceProvider;
/// <summary>
/// The main entry point for the application.
/// </summary>
[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<FormMain>());
}
/// <summary>
/// Конфигурация сервисов
/// </summary>
/// <param name="services"></param>
private static void ConfigureServices(ServiceCollection services)
{
// Логгер
services.AddLogging(option =>
{
option.SetMinimumLevel(LogLevel.Information);
option.AddNLog("nlog.config");
});
// IoC-контейнер, хранилища
services.AddTransient<ITransportTypeStorage, TransportTypeStorage>();
services.AddTransient<IRouteStorage, RouteStorage>();
services.AddTransient<IStopStorage, StopStorage>();
services.AddTransient<IScheduleStorage, ScheduleStorage>();
// IoC-контейнер, бизнес-логика
services.AddTransient<ITransportTypeLogic, TransportTypeLogic>();
services.AddTransient<IRouteLogic, RouteLogic>();
services.AddTransient<IStopLogic, StopLogic>();
services.AddTransient<IScheduleLogic, ScheduleLogic>();
// IoC-контейнер, основные формы
services.AddTransient<FormMain>();
services.AddTransient<FormSchedule>();
services.AddTransient<FormTransport>();
services.AddTransient<FormTransports>();
services.AddTransient<FormRoute>();
services.AddTransient<FormRoutes>();
services.AddTransient<FormRouteStop>();
services.AddTransient<FormStop>();
services.AddTransient<FormStops>();
// IoC-контейнер, формы для тестов
services.AddTransient<FormSchedulesTests>();
services.AddTransient<FormTransportTests>();
services.AddTransient<FormRoutesTests>();
services.AddTransient<FormStopsTests>();
// Запись DateTime Kind=Local в БД
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
}
}
}

View File

@ -0,0 +1,60 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.17">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="8.0.0" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.3.11" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\RouteDirectoryBusinessLogics\RouteDirectoryBusinessLogics.csproj" />
<ProjectReference Include="..\RouteDirectoryContracts\RouteDirectoryContracts.csproj" />
<ProjectReference Include="..\RouteDirectoryDatabaseImplement\RouteDirectoryDatabaseImplement.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Update="FormRoute.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormRoutes.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormRoutesTests.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormRouteStop.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormSchedulesTests.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormStop.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormStops.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormStopsTests.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormTransport.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="FormTransports.cs">
<SubType>Form</SubType>
</Compile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
autoReload="true" internalLogLevel="Info">
<targets>
<target xsi:type="File" name="tofile" fileName="log-${shortdate}.log" />
</targets>
<rules>
<logger name="*" minLevel="Debug" writeTo="tofile" />
</rules>
</nlog>
</configuration>