From f403a2f811d625e26607e3b66ac92bd3468514a8 Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 27 Jan 2025 18:24:55 +0500 Subject: [PATCH 1/7] =?UTF-8?q?=D0=93=D0=B8=D0=BF=D0=B5=D1=80=D1=82=D0=B0?= =?UTF-8?q?=D0=B1=D0=BB=D0=B8=D1=86=D0=B0=20parameter=5Fdata=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B7=D0=B4=D0=B0=D0=B5=D1=82=D1=81=D1=8F=20=D1=82=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=82=D0=BE=D0=B3=D0=B4=D0=B0,=20?= =?UTF-8?q?=D0=BA=D0=BE=D0=B3=D0=B4=D0=B0=20=D0=BE=D0=BD=D0=B0=20=D0=B5?= =?UTF-8?q?=D1=89=D0=B5=20=D0=B5=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD?= =?UTF-8?q?=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DD.Persistence.App/appsettings.json | 2 +- ....Persistence.Database.Postgres.Test.csproj | 26 ++++++ .../UnitTest1.cs | 85 +++++++++++++++++++ .../Extensions/EFExtensionsPartitioning.cs | 21 +++-- DD.Persistence.sln | 6 ++ 5 files changed, 131 insertions(+), 9 deletions(-) create mode 100644 DD.Persistence.Database.Postgres.Test/DD.Persistence.Database.Postgres.Test.csproj create mode 100644 DD.Persistence.Database.Postgres.Test/UnitTest1.cs diff --git a/DD.Persistence.App/appsettings.json b/DD.Persistence.App/appsettings.json index 7ad8c67..9b0d5be 100644 --- a/DD.Persistence.App/appsettings.json +++ b/DD.Persistence.App/appsettings.json @@ -6,7 +6,7 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Host=localhost;Database=persistence;Username=postgres;Password=postgres;Persist Security Info=True" + "DefaultConnection": "Host=localhost:5462;Database=persistence;Username=postgres;Password=postgres;Persist Security Info=True" }, "AllowedHosts": "*", "NeedUseKeyCloak": false, diff --git a/DD.Persistence.Database.Postgres.Test/DD.Persistence.Database.Postgres.Test.csproj b/DD.Persistence.Database.Postgres.Test/DD.Persistence.Database.Postgres.Test.csproj new file mode 100644 index 0000000..bc83156 --- /dev/null +++ b/DD.Persistence.Database.Postgres.Test/DD.Persistence.Database.Postgres.Test.csproj @@ -0,0 +1,26 @@ + + + + net9.0 + enable + enable + false + + + + + + + + + + + + + + + + + + + diff --git a/DD.Persistence.Database.Postgres.Test/UnitTest1.cs b/DD.Persistence.Database.Postgres.Test/UnitTest1.cs new file mode 100644 index 0000000..92cbcf9 --- /dev/null +++ b/DD.Persistence.Database.Postgres.Test/UnitTest1.cs @@ -0,0 +1,85 @@ +using DD.Persistence.Database.Entity; +using DD.Persistence.Database.Model; +using DD.Persistence.Database.Postgres.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace DD.Persistence.Database.Postgres.Test; + +public class UnitTest1 +{ + private string connectionString; + private IHost host; + + public UnitTest1() + { + connectionString = "Host=localhost;Port=5462;Username=postgres;Password=postgres;Database=persistence5"; + + + + var builder = Host.CreateApplicationBuilder(); + builder.Services.AddDbContext(options => + options.UseNpgsql(connectionString)); + + builder.Services.AddScoped(provider => provider.GetRequiredService()); + + host = builder.Build(); + using var scope = host.Services.CreateScope(); + var provider = scope.ServiceProvider; + + var context = provider.GetRequiredService(); + context.Database.EnsureCreatedAndMigrated(); + context.Database.AddPartitioning(); + context.SaveChanges(); + + + //using var scope2 = builder..CreateScope(); + //var scopedServices = scope.ServiceProvider; + + //var dbContext = scopedServices.GetRequiredService(); + //dbContext.Database.EnsureCreatedAndMigrated(); + //dbContext.SaveChanges(); + } + [Fact] + public void CreateHyperTable() + { + var entity = new ParameterData() { + DiscriminatorId = Guid.NewGuid(), + ParameterId = 1, + Timestamp = DateTime.UtcNow, + Value = "123" + }; + + var scope = host.Services.CreateScope(); + + var context = scope.ServiceProvider.GetRequiredService(); + + context.ParameterData.Add(entity); + context.SaveChanges(); + + entity.Timestamp = DateTime.UtcNow.AddDays(1); + context.ParameterData.Add(entity); + context.SaveChanges(); + + entity.Timestamp = DateTime.UtcNow.AddDays(2); + context.ParameterData.Add(entity); + context.SaveChanges(); + + entity.Timestamp = DateTime.UtcNow.AddDays(3); + context.ParameterData.Add(entity); + context.SaveChanges(); + + entity.Timestamp = DateTime.UtcNow.AddDays(4); + context.ParameterData.Add(entity); + context.SaveChanges(); + } + + //public static IHostBuilder CreateHostBuilder(string[] args) => + // Host.CreateDefaultBuilder(args) + // .ConfigureWebHostDefaults(webBuilder => + // { + // webBuilder.UseStartup(); + // }); +} diff --git a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs b/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs index 4ee2890..9fb78ee 100644 --- a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs +++ b/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs @@ -32,13 +32,18 @@ public static class EFExtensionsPartitioning return; } - const int sectionsNumber = 2; - const int chunkTimeInterval = 5; - var sqlString = $"SELECT create_hypertable('{tableAttribute.Name}'," + - $"'{nameof(ParameterData.Timestamp)}'," + - $"'{nameof(ParameterData.ParameterId)}'," + - $"{sectionsNumber}," + - $"chunk_time_interval => INTERVAL '{chunkTimeInterval} day');"; - db.ExecuteSqlRaw(sqlString); + var sqlCreateHypertableString = $"SELECT create_hypertable('{tableAttribute.Name}'," + + $"by_range('{nameof(ParameterData.Timestamp)}', INTERVAL '1 day'), if_not_exists => {true});"; + db.ExecuteSqlRaw(sqlCreateHypertableString); + + var sqlCreateDimensionString = $"SELECT add_dimension('{tableAttribute.Name}'," + + $"by_hash('{nameof(ParameterData.ParameterId)}', 1));"; + db.ExecuteSqlRaw(sqlCreateDimensionString); + //var sqlString = $"SELECT create_hypertable('{tableAttribute.Name}'," + + // $"'{nameof(ParameterData.Timestamp)}'," + + // $"'{nameof(ParameterData.ParameterId)}'," + + // $"{sectionsNumber}," + + // $"chunk_time_interval => INTERVAL '{chunkTimeInterval} day');"; + //db.ExecuteSqlRaw(sqlString); } } diff --git a/DD.Persistence.sln b/DD.Persistence.sln index 926e688..ca91e47 100644 --- a/DD.Persistence.sln +++ b/DD.Persistence.sln @@ -35,6 +35,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Элементы решен .gitea\workflows\integrationTests.yaml = .gitea\workflows\integrationTests.yaml EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DD.Persistence.Database.Postgres.Test", "DD.Persistence.Database.Postgres.Test\DD.Persistence.Database.Postgres.Test.csproj", "{47142566-9EAB-4FB5-92EC-9DCB02CAC890}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -85,6 +87,10 @@ Global {B8C774E6-6B75-41AC-B3CF-10BD3623B2FA}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8C774E6-6B75-41AC-B3CF-10BD3623B2FA}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8C774E6-6B75-41AC-B3CF-10BD3623B2FA}.Release|Any CPU.Build.0 = Release|Any CPU + {47142566-9EAB-4FB5-92EC-9DCB02CAC890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47142566-9EAB-4FB5-92EC-9DCB02CAC890}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47142566-9EAB-4FB5-92EC-9DCB02CAC890}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47142566-9EAB-4FB5-92EC-9DCB02CAC890}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE -- 2.45.2 From afd1e733f5c17fced6ed1e4b0719e7a54ca6e684 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Tue, 28 Jan 2025 12:15:58 +0500 Subject: [PATCH 2/7] =?UTF-8?q?=D0=90=D0=B2=D1=82=D0=BE=D1=82=D0=B5=D1=81?= =?UTF-8?q?=D1=82=20=D0=B4=D0=BB=D1=8F=20=D0=BF=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B8=20=D1=81=D0=BE=D0=B7=D0=B4=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D1=87=D0=B0=D0=BD=D0=BA=D0=BE=D0=B2=20=D0=B2=20timesc?= =?UTF-8?q?ale?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ....Persistence.Database.Postgres.Test.csproj | 1 + .../DbFixture.cs | 40 +++++++ .../UnitTest1.cs | 103 ++++++++---------- 3 files changed, 85 insertions(+), 59 deletions(-) create mode 100644 DD.Persistence.Database.Postgres.Test/DbFixture.cs diff --git a/DD.Persistence.Database.Postgres.Test/DD.Persistence.Database.Postgres.Test.csproj b/DD.Persistence.Database.Postgres.Test/DD.Persistence.Database.Postgres.Test.csproj index bc83156..859acb5 100644 --- a/DD.Persistence.Database.Postgres.Test/DD.Persistence.Database.Postgres.Test.csproj +++ b/DD.Persistence.Database.Postgres.Test/DD.Persistence.Database.Postgres.Test.csproj @@ -9,6 +9,7 @@ + diff --git a/DD.Persistence.Database.Postgres.Test/DbFixture.cs b/DD.Persistence.Database.Postgres.Test/DbFixture.cs new file mode 100644 index 0000000..cb1d153 --- /dev/null +++ b/DD.Persistence.Database.Postgres.Test/DbFixture.cs @@ -0,0 +1,40 @@ +using DD.Persistence.Database.Model; +using DD.Persistence.Database.Postgres.Extensions; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.DependencyInjection; + +namespace DD.Persistence.Database.Postgres.Test; +public class DbFixture : IDisposable +{ + public string connectionString { get; } + public ServiceProvider serviceProvider { get; private set; } + + public DbFixture() + { + connectionString = $"Host=localhost;Port=5462;Username=postgres;Password=postgres;Database={Guid.CreateVersion7()}"; + + var serviceCollection = new ServiceCollection(); + serviceCollection + .AddDbContext(options => options.UseNpgsql(connectionString), + ServiceLifetime.Transient); + + serviceProvider = serviceCollection.BuildServiceProvider(); + + var context = serviceProvider.GetRequiredService(); + context.Database.EnsureCreated(); + context.Database.AddPartitioning(); + context.SaveChanges(); + } + + public void Dispose() + { + var dbContext = new PersistencePostgresContext( + new DbContextOptionsBuilder() + .UseNpgsql(connectionString) + .Options); + + dbContext.Database.EnsureDeleted(); + + GC.SuppressFinalize(this); + } +} diff --git a/DD.Persistence.Database.Postgres.Test/UnitTest1.cs b/DD.Persistence.Database.Postgres.Test/UnitTest1.cs index 92cbcf9..a7fe654 100644 --- a/DD.Persistence.Database.Postgres.Test/UnitTest1.cs +++ b/DD.Persistence.Database.Postgres.Test/UnitTest1.cs @@ -1,85 +1,70 @@ using DD.Persistence.Database.Entity; -using DD.Persistence.Database.Model; -using DD.Persistence.Database.Postgres.Extensions; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Configuration; +using Mapster; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; +using Npgsql; namespace DD.Persistence.Database.Postgres.Test; -public class UnitTest1 +public class UnitTest1 : IClassFixture { - private string connectionString; - private IHost host; + private ServiceProvider _serviceProvider; + private string _connectionString; - public UnitTest1() + public UnitTest1(DbFixture fixture) { - connectionString = "Host=localhost;Port=5462;Username=postgres;Password=postgres;Database=persistence5"; - - - - var builder = Host.CreateApplicationBuilder(); - builder.Services.AddDbContext(options => - options.UseNpgsql(connectionString)); - - builder.Services.AddScoped(provider => provider.GetRequiredService()); - - host = builder.Build(); - using var scope = host.Services.CreateScope(); - var provider = scope.ServiceProvider; - - var context = provider.GetRequiredService(); - context.Database.EnsureCreatedAndMigrated(); - context.Database.AddPartitioning(); - context.SaveChanges(); - - - //using var scope2 = builder..CreateScope(); - //var scopedServices = scope.ServiceProvider; - - //var dbContext = scopedServices.GetRequiredService(); - //dbContext.Database.EnsureCreatedAndMigrated(); - //dbContext.SaveChanges(); + _serviceProvider = fixture.serviceProvider; + _connectionString = fixture.connectionString; } + [Fact] public void CreateHyperTable() { - var entity = new ParameterData() { + var entity = new ParameterData() + { DiscriminatorId = Guid.NewGuid(), ParameterId = 1, Timestamp = DateTime.UtcNow, Value = "123" }; - var scope = host.Services.CreateScope(); + using (var context = _serviceProvider.GetService()!) + { + context.ParameterData.Add(entity); - var context = scope.ServiceProvider.GetRequiredService(); + var entity2 = entity.Adapt(); + entity2.ParameterId = 2; + context.ParameterData.Add(entity2); - context.ParameterData.Add(entity); - context.SaveChanges(); + var entity3 = entity2.Adapt(); + entity3.ParameterId = 3; + entity3.Timestamp = DateTime.UtcNow.AddDays(2); + context.ParameterData.Add(entity3); - entity.Timestamp = DateTime.UtcNow.AddDays(1); - context.ParameterData.Add(entity); - context.SaveChanges(); + var entity4 = entity3.Adapt(); + entity4.ParameterId = 4; + context.ParameterData.Add(entity4); - entity.Timestamp = DateTime.UtcNow.AddDays(2); - context.ParameterData.Add(entity); - context.SaveChanges(); + context.SaveChanges(); + } - entity.Timestamp = DateTime.UtcNow.AddDays(3); - context.ParameterData.Add(entity); - context.SaveChanges(); + var chunksCount = 0; + using (var connection = new NpgsqlConnection(_connectionString)) + { + connection.Open(); + string sql = "select count(*) from (select show_chunks('parameter_data'));"; - entity.Timestamp = DateTime.UtcNow.AddDays(4); - context.ParameterData.Add(entity); - context.SaveChanges(); + using (var command = new NpgsqlCommand(sql, connection)) + { + using (var reader = command.ExecuteReader()) + { + while (reader.Read()) + { + chunksCount += reader.GetInt32(0); + } + } + } + } + + Assert.Equal(2, chunksCount); } - - //public static IHostBuilder CreateHostBuilder(string[] args) => - // Host.CreateDefaultBuilder(args) - // .ConfigureWebHostDefaults(webBuilder => - // { - // webBuilder.UseStartup(); - // }); } -- 2.45.2 From c2de8a0cc27a24e066b1cccf50710feefa3d5355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Tue, 28 Jan 2025 12:30:58 +0500 Subject: [PATCH 3/7] =?UTF-8?q?=D0=9C=D0=B5=D0=BB=D0=BA=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8:=20=D1=83=D0=B4=D0=B0?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BC=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D0=B5=D0=B2,=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B5=D0=B8=D0=BC=D0=B5=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=84=D0=B0=D0=B9=D0=BB=D0=BE=D0=B2=20=D0=B8=20?= =?UTF-8?q?=D1=82.=D0=B4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DD.Persistence.App/appsettings.json | 2 +- .../{UnitTest1.cs => UnitTestCheckHyperTables.cs} | 6 +++--- .../Extensions/EFExtensionsPartitioning.cs | 12 +++--------- 3 files changed, 7 insertions(+), 13 deletions(-) rename DD.Persistence.Database.Postgres.Test/{UnitTest1.cs => UnitTestCheckHyperTables.cs} (91%) diff --git a/DD.Persistence.App/appsettings.json b/DD.Persistence.App/appsettings.json index 9b0d5be..7ad8c67 100644 --- a/DD.Persistence.App/appsettings.json +++ b/DD.Persistence.App/appsettings.json @@ -6,7 +6,7 @@ } }, "ConnectionStrings": { - "DefaultConnection": "Host=localhost:5462;Database=persistence;Username=postgres;Password=postgres;Persist Security Info=True" + "DefaultConnection": "Host=localhost;Database=persistence;Username=postgres;Password=postgres;Persist Security Info=True" }, "AllowedHosts": "*", "NeedUseKeyCloak": false, diff --git a/DD.Persistence.Database.Postgres.Test/UnitTest1.cs b/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs similarity index 91% rename from DD.Persistence.Database.Postgres.Test/UnitTest1.cs rename to DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs index a7fe654..9c96454 100644 --- a/DD.Persistence.Database.Postgres.Test/UnitTest1.cs +++ b/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs @@ -5,19 +5,19 @@ using Npgsql; namespace DD.Persistence.Database.Postgres.Test; -public class UnitTest1 : IClassFixture +public class UnitTestCheckHyperTables : IClassFixture { private ServiceProvider _serviceProvider; private string _connectionString; - public UnitTest1(DbFixture fixture) + public UnitTestCheckHyperTables(DbFixture fixture) { _serviceProvider = fixture.serviceProvider; _connectionString = fixture.connectionString; } [Fact] - public void CreateHyperTable() + public void CreateHyperTable_For_ParameterData_Return_Success() { var entity = new ParameterData() { diff --git a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs b/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs index 9fb78ee..374fa6e 100644 --- a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs +++ b/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs @@ -25,6 +25,7 @@ public static class EFExtensionsPartitioning /// private static void AddParameterDataPartitioning(this DatabaseFacade db) { + var dayCount = 1; var type = typeof(ParameterData); var tableAttribute = type.GetCustomAttribute(); if (tableAttribute is null) @@ -33,17 +34,10 @@ public static class EFExtensionsPartitioning } var sqlCreateHypertableString = $"SELECT create_hypertable('{tableAttribute.Name}'," + - $"by_range('{nameof(ParameterData.Timestamp)}', INTERVAL '1 day'), if_not_exists => {true});"; + $"by_range('{nameof(ParameterData.Timestamp)}', INTERVAL '{dayCount} day'), if_not_exists => {true});"; db.ExecuteSqlRaw(sqlCreateHypertableString); var sqlCreateDimensionString = $"SELECT add_dimension('{tableAttribute.Name}'," + - $"by_hash('{nameof(ParameterData.ParameterId)}', 1));"; - db.ExecuteSqlRaw(sqlCreateDimensionString); - //var sqlString = $"SELECT create_hypertable('{tableAttribute.Name}'," + - // $"'{nameof(ParameterData.Timestamp)}'," + - // $"'{nameof(ParameterData.ParameterId)}'," + - // $"{sectionsNumber}," + - // $"chunk_time_interval => INTERVAL '{chunkTimeInterval} day');"; - //db.ExecuteSqlRaw(sqlString); + $"by_hash('{nameof(ParameterData.ParameterId)}', {dayCount}));"; } } -- 2.45.2 From dac42a88391589b4d1ce231785f58912f8a66fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Tue, 28 Jan 2025 12:42:01 +0500 Subject: [PATCH 4/7] =?UTF-8?q?=D0=A0=D0=B5=D1=84=D0=B0=D0=BA=D1=82=D0=BE?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D0=B3=20=D0=BC=D0=B5=D1=82=D0=BE=D0=B4=D0=B0?= =?UTF-8?q?=20CreateHyperTable=5FFor=5FParameterData=5FReturn=5FSuccess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UnitTestCheckHyperTables.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs b/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs index 9c96454..f0b8749 100644 --- a/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs +++ b/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs @@ -1,5 +1,6 @@ using DD.Persistence.Database.Entity; using Mapster; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Npgsql; @@ -19,6 +20,8 @@ public class UnitTestCheckHyperTables : IClassFixture [Fact] public void CreateHyperTable_For_ParameterData_Return_Success() { + var chunksCount = 0; + var entity = new ParameterData() { DiscriminatorId = Guid.NewGuid(), @@ -45,24 +48,11 @@ public class UnitTestCheckHyperTables : IClassFixture context.ParameterData.Add(entity4); context.SaveChanges(); - } - var chunksCount = 0; - using (var connection = new NpgsqlConnection(_connectionString)) - { - connection.Open(); string sql = "select count(*) from (select show_chunks('parameter_data'));"; + var queryRow = context.Database.SqlQueryRaw(sql); - using (var command = new NpgsqlCommand(sql, connection)) - { - using (var reader = command.ExecuteReader()) - { - while (reader.Read()) - { - chunksCount += reader.GetInt32(0); - } - } - } + chunksCount = queryRow.AsEnumerable().FirstOrDefault(); } Assert.Equal(2, chunksCount); -- 2.45.2 From aa88e90320bda54f27b7c857922fc1a851f3351f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Tue, 28 Jan 2025 13:08:49 +0500 Subject: [PATCH 5/7] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=B0=D1=80=D1=82=D0=B8=D1=86=D0=B8?= =?UTF-8?q?=D0=BE=D0=BD=D0=B8=D1=80=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D1=8F=20?= =?UTF-8?q?=D0=BF=D0=BE=20ParameterData.DiscriminatorId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Extensions/EFExtensionsPartitioning.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs b/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs index 374fa6e..a432d77 100644 --- a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs +++ b/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs @@ -26,6 +26,7 @@ public static class EFExtensionsPartitioning private static void AddParameterDataPartitioning(this DatabaseFacade db) { var dayCount = 1; + var sectionCount = 1; var type = typeof(ParameterData); var tableAttribute = type.GetCustomAttribute(); if (tableAttribute is null) @@ -37,7 +38,10 @@ public static class EFExtensionsPartitioning $"by_range('{nameof(ParameterData.Timestamp)}', INTERVAL '{dayCount} day'), if_not_exists => {true});"; db.ExecuteSqlRaw(sqlCreateHypertableString); - var sqlCreateDimensionString = $"SELECT add_dimension('{tableAttribute.Name}'," + - $"by_hash('{nameof(ParameterData.ParameterId)}', {dayCount}));"; + var sqlCreateDimensionParameterId = $"SELECT add_dimension('{tableAttribute.Name}'," + + $"by_hash('{nameof(ParameterData.ParameterId)}', {sectionCount}));"; + + var sqlCreateDimensionDiscriminatorId = $"SELECT add_dimension('{tableAttribute.Name}'," + + $"by_hash('{nameof(ParameterData.DiscriminatorId)}', {sectionCount}));"; } } -- 2.45.2 From 6249418f2e24191638c57c624c45214883ae84de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D1=8F=20=D0=91=D0=B8=D0=B7=D1=8E=D0=BA=D0=BE?= =?UTF-8?q?=D0=B2=D0=B0?= Date: Tue, 28 Jan 2025 13:10:14 +0500 Subject: [PATCH 6/7] =?UTF-8?q?=D0=A3=D0=B1=D1=80=D0=B0=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BD=D0=B5=D0=B8=D1=81=D0=BF=D0=BE=D0=BB=D1=8C=D0=B7=D1=83?= =?UTF-8?q?=D0=B5=D0=BC=D0=B0=D1=8F=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D0=B0=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DD.Persistence.Database.Postgres.Test/DbFixture.cs | 2 +- .../UnitTestCheckHyperTables.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/DD.Persistence.Database.Postgres.Test/DbFixture.cs b/DD.Persistence.Database.Postgres.Test/DbFixture.cs index cb1d153..c3a0c64 100644 --- a/DD.Persistence.Database.Postgres.Test/DbFixture.cs +++ b/DD.Persistence.Database.Postgres.Test/DbFixture.cs @@ -6,7 +6,7 @@ using Microsoft.Extensions.DependencyInjection; namespace DD.Persistence.Database.Postgres.Test; public class DbFixture : IDisposable { - public string connectionString { get; } + private string connectionString { get; } public ServiceProvider serviceProvider { get; private set; } public DbFixture() diff --git a/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs b/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs index f0b8749..3179a67 100644 --- a/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs +++ b/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs @@ -9,12 +9,10 @@ namespace DD.Persistence.Database.Postgres.Test; public class UnitTestCheckHyperTables : IClassFixture { private ServiceProvider _serviceProvider; - private string _connectionString; public UnitTestCheckHyperTables(DbFixture fixture) { _serviceProvider = fixture.serviceProvider; - _connectionString = fixture.connectionString; } [Fact] -- 2.45.2 From 9d40a4a18d9aaf10b333f8a2cb8a57a1ff153d6d Mon Sep 17 00:00:00 2001 From: Olga Nemt Date: Mon, 3 Feb 2025 15:28:52 +0500 Subject: [PATCH 7/7] =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=B8=D1=87=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B2=D0=BE=20=D0=BF=D0=B0=D1=80=D1=82=D0=B8=D1=86=D0=B8?= =?UTF-8?q?=D0=B9=20partitonCount=20=3D=20128.=20=D0=9D=D0=B5=D0=BE=D0=B1?= =?UTF-8?q?=D1=85=D0=BE=D0=B4=D0=B8=D0=BC=D0=BE,=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D1=82=D0=BE=D0=B3=D0=BE,=20=D1=87=D1=82=D0=BE=D0=B1=D1=8B=20?= =?UTF-8?q?=D0=BF=D1=80=D0=B8=20=D0=B8=D0=B7=D0=BC=D0=B5=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B8=20DescriptionId=20=D0=B8=20ParameterId=20=D1=81?= =?UTF-8?q?=D0=BE=D0=B7=D0=B4=D0=B0=D0=B2=D0=B0=D0=BB=D0=B8=D1=81=D1=8C=20?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D1=8B=D0=B5=20=D1=87=D0=B0=D0=BD=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../UnitTestCheckHyperTables.cs | 11 +- .../Extensions/EFExtensionsPartitioning.cs | 10 +- ...ner.cs => 20250203061429_Init.Designer.cs} | 142 ++++++++---------- ...2120353_Init.cs => 20250203061429_Init.cs} | 3 - ...PersistencePostgresContextModelSnapshot.cs | 140 ++++++++--------- .../PersistencePostgresContext.cs | 4 +- 6 files changed, 146 insertions(+), 164 deletions(-) rename DD.Persistence.Database.Postgres/Migrations/{20250122120353_Init.Designer.cs => 20250203061429_Init.Designer.cs} (91%) rename DD.Persistence.Database.Postgres/Migrations/{20250122120353_Init.cs => 20250203061429_Init.cs} (94%) diff --git a/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs b/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs index 3179a67..6f58046 100644 --- a/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs +++ b/DD.Persistence.Database.Postgres.Test/UnitTestCheckHyperTables.cs @@ -38,13 +38,20 @@ public class UnitTestCheckHyperTables : IClassFixture var entity3 = entity2.Adapt(); entity3.ParameterId = 3; - entity3.Timestamp = DateTime.UtcNow.AddDays(2); context.ParameterData.Add(entity3); var entity4 = entity3.Adapt(); entity4.ParameterId = 4; context.ParameterData.Add(entity4); + var entity5 = entity3.Adapt(); + entity5.Timestamp = DateTime.UtcNow.AddDays(1).AddHours(1); + context.ParameterData.Add(entity5); + + var entity6 = entity3.Adapt(); + entity6.DiscriminatorId = Guid.CreateVersion7(); + context.ParameterData.Add(entity6); + context.SaveChanges(); string sql = "select count(*) from (select show_chunks('parameter_data'));"; @@ -53,6 +60,6 @@ public class UnitTestCheckHyperTables : IClassFixture chunksCount = queryRow.AsEnumerable().FirstOrDefault(); } - Assert.Equal(2, chunksCount); + Assert.Equal(5, chunksCount); } } diff --git a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs b/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs index a432d77..0860dc3 100644 --- a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs +++ b/DD.Persistence.Database.Postgres/Extensions/EFExtensionsPartitioning.cs @@ -26,7 +26,7 @@ public static class EFExtensionsPartitioning private static void AddParameterDataPartitioning(this DatabaseFacade db) { var dayCount = 1; - var sectionCount = 1; + var sectionCount = 128; var type = typeof(ParameterData); var tableAttribute = type.GetCustomAttribute(); if (tableAttribute is null) @@ -38,10 +38,12 @@ public static class EFExtensionsPartitioning $"by_range('{nameof(ParameterData.Timestamp)}', INTERVAL '{dayCount} day'), if_not_exists => {true});"; db.ExecuteSqlRaw(sqlCreateHypertableString); - var sqlCreateDimensionParameterId = $"SELECT add_dimension('{tableAttribute.Name}'," + - $"by_hash('{nameof(ParameterData.ParameterId)}', {sectionCount}));"; + var sqlCreateDimensionParameterId = $"SELECT add_dimension('{tableAttribute.Name}'," + + $"by_hash('{nameof(ParameterData.ParameterId)}', {sectionCount}), if_not_exists => {true});"; + db.ExecuteSqlRaw(sqlCreateDimensionParameterId); var sqlCreateDimensionDiscriminatorId = $"SELECT add_dimension('{tableAttribute.Name}'," + - $"by_hash('{nameof(ParameterData.DiscriminatorId)}', {sectionCount}));"; + $"by_hash('{nameof(ParameterData.DiscriminatorId)}', {sectionCount}), if_not_exists => {true});"; + db.ExecuteSqlRaw(sqlCreateDimensionDiscriminatorId); } } diff --git a/DD.Persistence.Database.Postgres/Migrations/20250122120353_Init.Designer.cs b/DD.Persistence.Database.Postgres/Migrations/20250203061429_Init.Designer.cs similarity index 91% rename from DD.Persistence.Database.Postgres/Migrations/20250122120353_Init.Designer.cs rename to DD.Persistence.Database.Postgres/Migrations/20250203061429_Init.Designer.cs index 81695fb..bdeaf87 100644 --- a/DD.Persistence.Database.Postgres/Migrations/20250122120353_Init.Designer.cs +++ b/DD.Persistence.Database.Postgres/Migrations/20250203061429_Init.Designer.cs @@ -13,7 +13,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace DD.Persistence.Database.Postgres.Migrations { [DbContext(typeof(PersistencePostgresContext))] - [Migration("20250122120353_Init")] + [Migration("20250203061429_Init")] partial class Init { /// @@ -26,6 +26,47 @@ namespace DD.Persistence.Database.Postgres.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + modelBuilder.Entity("DD.Persistence.Database.Entity.ChangeLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasComment("Ключ записи"); + + b.Property("Creation") + .HasColumnType("timestamp with time zone") + .HasComment("Дата создания записи"); + + b.Property("IdAuthor") + .HasColumnType("uuid") + .HasComment("Автор изменения"); + + b.Property("IdDiscriminator") + .HasColumnType("uuid") + .HasComment("Дискриминатор таблицы"); + + b.Property("IdEditor") + .HasColumnType("uuid") + .HasComment("Редактор"); + + b.Property("IdNext") + .HasColumnType("uuid") + .HasComment("Id заменяющей записи"); + + b.Property("Obsolete") + .HasColumnType("timestamp with time zone") + .HasComment("Дата устаревания (например при удалении)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("jsonb") + .HasComment("Значение"); + + b.HasKey("Id"); + + b.ToTable("change_log"); + }); + modelBuilder.Entity("DD.Persistence.Database.Entity.DataScheme", b => { b.Property("DiscriminatorId") @@ -88,6 +129,29 @@ namespace DD.Persistence.Database.Postgres.Migrations b.ToTable("parameter_data"); }); + modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b => + { + b.Property("Key") + .HasColumnType("uuid") + .HasComment("Ключ"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasComment("Дата создания уставки"); + + b.Property("IdUser") + .HasColumnType("uuid") + .HasComment("Id автора последнего изменения"); + + b.Property("Value") + .HasColumnType("jsonb") + .HasComment("Значение уставки"); + + b.HasKey("Key", "Timestamp"); + + b.ToTable("setpoint"); + }); + modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b => { b.Property("EventId") @@ -143,82 +207,6 @@ namespace DD.Persistence.Database.Postgres.Migrations b.ToTable("timestamped_values"); }); - modelBuilder.Entity("DD.Persistence.Database.Model.ChangeLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasComment("Ключ записи"); - - b.Property("Creation") - .HasColumnType("timestamp with time zone") - .HasComment("Дата создания записи"); - - b.Property("DepthEnd") - .HasColumnType("double precision") - .HasComment("Глубина забоя на дату окончания интервала"); - - b.Property("DepthStart") - .HasColumnType("double precision") - .HasComment("Глубина забоя на дату начала интервала"); - - b.Property("IdAuthor") - .HasColumnType("uuid") - .HasComment("Автор изменения"); - - b.Property("IdDiscriminator") - .HasColumnType("uuid") - .HasComment("Дискриминатор таблицы"); - - b.Property("IdEditor") - .HasColumnType("uuid") - .HasComment("Редактор"); - - b.Property("IdNext") - .HasColumnType("uuid") - .HasComment("Id заменяющей записи"); - - b.Property("IdSection") - .HasColumnType("uuid") - .HasComment("Ключ секции"); - - b.Property("Obsolete") - .HasColumnType("timestamp with time zone") - .HasComment("Дата устаревания (например при удалении)"); - - b.Property("Value") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("Значение"); - - b.HasKey("Id"); - - b.ToTable("change_log"); - }); - - modelBuilder.Entity("DD.Persistence.Database.Model.Setpoint", b => - { - b.Property("Key") - .HasColumnType("uuid") - .HasComment("Ключ"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasComment("Дата создания уставки"); - - b.Property("IdUser") - .HasColumnType("uuid") - .HasComment("Id автора последнего изменения"); - - b.Property("Value") - .HasColumnType("jsonb") - .HasComment("Значение уставки"); - - b.HasKey("Key", "Timestamp"); - - b.ToTable("setpoint"); - }); - modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b => { b.HasOne("DD.Persistence.Database.Entity.DataSourceSystem", "System") diff --git a/DD.Persistence.Database.Postgres/Migrations/20250122120353_Init.cs b/DD.Persistence.Database.Postgres/Migrations/20250203061429_Init.cs similarity index 94% rename from DD.Persistence.Database.Postgres/Migrations/20250122120353_Init.cs rename to DD.Persistence.Database.Postgres/Migrations/20250203061429_Init.cs index 6f56873..df996bc 100644 --- a/DD.Persistence.Database.Postgres/Migrations/20250122120353_Init.cs +++ b/DD.Persistence.Database.Postgres/Migrations/20250203061429_Init.cs @@ -23,9 +23,6 @@ namespace DD.Persistence.Database.Postgres.Migrations Creation = table.Column(type: "timestamp with time zone", nullable: false, comment: "Дата создания записи"), Obsolete = table.Column(type: "timestamp with time zone", nullable: true, comment: "Дата устаревания (например при удалении)"), IdNext = table.Column(type: "uuid", nullable: true, comment: "Id заменяющей записи"), - DepthStart = table.Column(type: "double precision", nullable: false, comment: "Глубина забоя на дату начала интервала"), - DepthEnd = table.Column(type: "double precision", nullable: false, comment: "Глубина забоя на дату окончания интервала"), - IdSection = table.Column(type: "uuid", nullable: false, comment: "Ключ секции"), Value = table.Column(type: "jsonb", nullable: false, comment: "Значение") }, constraints: table => diff --git a/DD.Persistence.Database.Postgres/Migrations/PersistencePostgresContextModelSnapshot.cs b/DD.Persistence.Database.Postgres/Migrations/PersistencePostgresContextModelSnapshot.cs index 3db9dda..5c5ad2e 100644 --- a/DD.Persistence.Database.Postgres/Migrations/PersistencePostgresContextModelSnapshot.cs +++ b/DD.Persistence.Database.Postgres/Migrations/PersistencePostgresContextModelSnapshot.cs @@ -23,6 +23,47 @@ namespace DD.Persistence.Database.Postgres.Migrations NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + modelBuilder.Entity("DD.Persistence.Database.Entity.ChangeLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasComment("Ключ записи"); + + b.Property("Creation") + .HasColumnType("timestamp with time zone") + .HasComment("Дата создания записи"); + + b.Property("IdAuthor") + .HasColumnType("uuid") + .HasComment("Автор изменения"); + + b.Property("IdDiscriminator") + .HasColumnType("uuid") + .HasComment("Дискриминатор таблицы"); + + b.Property("IdEditor") + .HasColumnType("uuid") + .HasComment("Редактор"); + + b.Property("IdNext") + .HasColumnType("uuid") + .HasComment("Id заменяющей записи"); + + b.Property("Obsolete") + .HasColumnType("timestamp with time zone") + .HasComment("Дата устаревания (например при удалении)"); + + b.Property("Value") + .IsRequired() + .HasColumnType("jsonb") + .HasComment("Значение"); + + b.HasKey("Id"); + + b.ToTable("change_log"); + }); + modelBuilder.Entity("DD.Persistence.Database.Entity.DataScheme", b => { b.Property("DiscriminatorId") @@ -85,6 +126,29 @@ namespace DD.Persistence.Database.Postgres.Migrations b.ToTable("parameter_data"); }); + modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b => + { + b.Property("Key") + .HasColumnType("uuid") + .HasComment("Ключ"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasComment("Дата создания уставки"); + + b.Property("IdUser") + .HasColumnType("uuid") + .HasComment("Id автора последнего изменения"); + + b.Property("Value") + .HasColumnType("jsonb") + .HasComment("Значение уставки"); + + b.HasKey("Key", "Timestamp"); + + b.ToTable("setpoint"); + }); + modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b => { b.Property("EventId") @@ -140,82 +204,6 @@ namespace DD.Persistence.Database.Postgres.Migrations b.ToTable("timestamped_values"); }); - modelBuilder.Entity("DD.Persistence.Database.Model.ChangeLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasComment("Ключ записи"); - - b.Property("Creation") - .HasColumnType("timestamp with time zone") - .HasComment("Дата создания записи"); - - b.Property("DepthEnd") - .HasColumnType("double precision") - .HasComment("Глубина забоя на дату окончания интервала"); - - b.Property("DepthStart") - .HasColumnType("double precision") - .HasComment("Глубина забоя на дату начала интервала"); - - b.Property("IdAuthor") - .HasColumnType("uuid") - .HasComment("Автор изменения"); - - b.Property("IdDiscriminator") - .HasColumnType("uuid") - .HasComment("Дискриминатор таблицы"); - - b.Property("IdEditor") - .HasColumnType("uuid") - .HasComment("Редактор"); - - b.Property("IdNext") - .HasColumnType("uuid") - .HasComment("Id заменяющей записи"); - - b.Property("IdSection") - .HasColumnType("uuid") - .HasComment("Ключ секции"); - - b.Property("Obsolete") - .HasColumnType("timestamp with time zone") - .HasComment("Дата устаревания (например при удалении)"); - - b.Property("Value") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("Значение"); - - b.HasKey("Id"); - - b.ToTable("change_log"); - }); - - modelBuilder.Entity("DD.Persistence.Database.Model.Setpoint", b => - { - b.Property("Key") - .HasColumnType("uuid") - .HasComment("Ключ"); - - b.Property("Timestamp") - .HasColumnType("timestamp with time zone") - .HasComment("Дата создания уставки"); - - b.Property("IdUser") - .HasColumnType("uuid") - .HasComment("Id автора последнего изменения"); - - b.Property("Value") - .HasColumnType("jsonb") - .HasComment("Значение уставки"); - - b.HasKey("Key", "Timestamp"); - - b.ToTable("setpoint"); - }); - modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b => { b.HasOne("DD.Persistence.Database.Entity.DataSourceSystem", "System") diff --git a/DD.Persistence.Database.Postgres/PersistencePostgresContext.cs b/DD.Persistence.Database.Postgres/PersistencePostgresContext.cs index 6cd8955..3da502f 100644 --- a/DD.Persistence.Database.Postgres/PersistencePostgresContext.cs +++ b/DD.Persistence.Database.Postgres/PersistencePostgresContext.cs @@ -1,9 +1,9 @@ -using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore; namespace DD.Persistence.Database.Model; /// -/// EF Postgres +/// EF контекст для базы данных Postgres /// public partial class PersistencePostgresContext : PersistenceDbContext { -- 2.45.2