From 4513de06fa1d532aef0a6d0cd9403aab8dd2aed3 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Wed, 5 Feb 2025 12:19:45 +0500 Subject: [PATCH 1/3] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BD=D0=B5=D1=81?= =?UTF-8?q?=D1=82=D0=B8=20=D1=81=D0=BE=D0=B4=D0=B5=D1=80=D0=B6=D0=B8=D0=BC?= =?UTF-8?q?=D0=BE=D0=B5=20=D0=BF=D1=80=D0=BE=D0=B5=D0=BA=D1=82=D0=B0=20DD.?= =?UTF-8?q?Persistence.Repository=20=D0=B2=20DD.Persistence.Database?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DD.Persistence.API/Startup.cs | 3 +- .../DD.Persistence.Database.Postgres.csproj | 2 - .../DependencyInjection.cs | 33 ------------- .../DD.Persistence.Database.csproj | 2 + .../DependencyInjection.cs | 47 +++++++++++++++++++ .../Extensions/EFExtensionsSortBy.cs | 2 +- .../Helpers/CyclicArray.cs | 0 .../Helpers/QueryBuilders.cs | 0 .../Repositories/ChangeLogRepository.cs | 8 ++-- .../Repositories/DataSchemeRepository.cs | 0 .../DataSourceSystemRepository.cs | 0 .../Repositories/ParameterRepository.cs | 0 .../Repositories/SetpointRepository.cs | 0 .../Repositories/TechMessagesRepository.cs | 0 .../TimestampedValuesRepository.cs | 0 .../DataSchemeCachedRepository.cs | 0 .../DataSourceSystemCachedRepository.cs | 0 .../TimestampedValuesCachedRepository.cs | 0 18 files changed, 56 insertions(+), 41 deletions(-) create mode 100644 DD.Persistence.Database/DependencyInjection.cs rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Extensions/EFExtensionsSortBy.cs (99%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Helpers/CyclicArray.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Helpers/QueryBuilders.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Repositories/ChangeLogRepository.cs (96%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Repositories/DataSchemeRepository.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Repositories/DataSourceSystemRepository.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Repositories/ParameterRepository.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Repositories/SetpointRepository.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Repositories/TechMessagesRepository.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/Repositories/TimestampedValuesRepository.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/RepositoriesCached/DataSchemeCachedRepository.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/RepositoriesCached/DataSourceSystemCachedRepository.cs (100%) rename {DD.Persistence.Database.Postgres => DD.Persistence.Database}/RepositoriesCached/TimestampedValuesCachedRepository.cs (100%) diff --git a/DD.Persistence.API/Startup.cs b/DD.Persistence.API/Startup.cs index bc78548..a3c3efe 100644 --- a/DD.Persistence.API/Startup.cs +++ b/DD.Persistence.API/Startup.cs @@ -1,4 +1,5 @@ -using DD.Persistence.Database.Model; +using DD.Persistence.Database; +using DD.Persistence.Database.Model; using DD.Persistence.Database.Postgres.Extensions; namespace DD.Persistence.API; diff --git a/DD.Persistence.Database.Postgres/DD.Persistence.Database.Postgres.csproj b/DD.Persistence.Database.Postgres/DD.Persistence.Database.Postgres.csproj index 80b6736..bf406a6 100644 --- a/DD.Persistence.Database.Postgres/DD.Persistence.Database.Postgres.csproj +++ b/DD.Persistence.Database.Postgres/DD.Persistence.Database.Postgres.csproj @@ -7,13 +7,11 @@ - all runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/DD.Persistence.Database.Postgres/DependencyInjection.cs b/DD.Persistence.Database.Postgres/DependencyInjection.cs index 0509061..df84bb3 100644 --- a/DD.Persistence.Database.Postgres/DependencyInjection.cs +++ b/DD.Persistence.Database.Postgres/DependencyInjection.cs @@ -24,37 +24,4 @@ public static class DependencyInjection return services; } - - public static void MapsterSetup() - { - TypeAdapterConfig.GlobalSettings.Default.Config - .ForType() - .Ignore(dest => dest.System, dest => dest.SystemId); - - TypeAdapterConfig.NewConfig() - .Map(dest => dest.Value, src => new ChangeLogValuesDto() - { - Value = src.Value, - Id = src.Id - }); - } - - public static IServiceCollection AddInfrastructure(this IServiceCollection services) - { - var typeAdapterConfig = TypeAdapterConfig.GlobalSettings; - typeAdapterConfig.RuleMap.Clear(); - typeAdapterConfig.Scan(Assembly.GetExecutingAssembly()); - - MapsterSetup(); - - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - services.AddTransient(); - - return services; - } } diff --git a/DD.Persistence.Database/DD.Persistence.Database.csproj b/DD.Persistence.Database/DD.Persistence.Database.csproj index 9303e6a..65f8d54 100644 --- a/DD.Persistence.Database/DD.Persistence.Database.csproj +++ b/DD.Persistence.Database/DD.Persistence.Database.csproj @@ -7,11 +7,13 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/DD.Persistence.Database/DependencyInjection.cs b/DD.Persistence.Database/DependencyInjection.cs new file mode 100644 index 0000000..c04d9e5 --- /dev/null +++ b/DD.Persistence.Database/DependencyInjection.cs @@ -0,0 +1,47 @@ +using DD.Persistence.Database.Entity; +using DD.Persistence.Database.Postgres.Repositories; +using DD.Persistence.Database.Postgres.RepositoriesCached; +using DD.Persistence.Database.Repositories; +using DD.Persistence.Models; +using DD.Persistence.Repositories; +using Mapster; +using Microsoft.Extensions.DependencyInjection; +using System.Reflection; + +namespace DD.Persistence.Database; + +public static class DependencyInjection +{ + public static void MapsterSetup() + { + TypeAdapterConfig.GlobalSettings.Default.Config + .ForType() + .Ignore(dest => dest.System, dest => dest.SystemId); + + TypeAdapterConfig.NewConfig() + .Map(dest => dest.Value, src => new ChangeLogValuesDto() + { + Value = src.Value, + Id = src.Id + }); + } + + public static IServiceCollection AddInfrastructure(this IServiceCollection services) + { + var typeAdapterConfig = TypeAdapterConfig.GlobalSettings; + typeAdapterConfig.RuleMap.Clear(); + typeAdapterConfig.Scan(Assembly.GetExecutingAssembly()); + + MapsterSetup(); + + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + return services; + } +} diff --git a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsSortBy.cs b/DD.Persistence.Database/Extensions/EFExtensionsSortBy.cs similarity index 99% rename from DD.Persistence.Database.Postgres/Extensions/EFExtensionsSortBy.cs rename to DD.Persistence.Database/Extensions/EFExtensionsSortBy.cs index 3af7ae0..10818a4 100644 --- a/DD.Persistence.Database.Postgres/Extensions/EFExtensionsSortBy.cs +++ b/DD.Persistence.Database/Extensions/EFExtensionsSortBy.cs @@ -2,7 +2,7 @@ using System.Collections.Concurrent; using System.Linq.Expressions; using System.Reflection; -namespace DD.Persistence.Database.Postgres.Extensions; +namespace DD.Persistence.Database.Extensions; public static class EFExtensionsSortBy { diff --git a/DD.Persistence.Database.Postgres/Helpers/CyclicArray.cs b/DD.Persistence.Database/Helpers/CyclicArray.cs similarity index 100% rename from DD.Persistence.Database.Postgres/Helpers/CyclicArray.cs rename to DD.Persistence.Database/Helpers/CyclicArray.cs diff --git a/DD.Persistence.Database.Postgres/Helpers/QueryBuilders.cs b/DD.Persistence.Database/Helpers/QueryBuilders.cs similarity index 100% rename from DD.Persistence.Database.Postgres/Helpers/QueryBuilders.cs rename to DD.Persistence.Database/Helpers/QueryBuilders.cs diff --git a/DD.Persistence.Database.Postgres/Repositories/ChangeLogRepository.cs b/DD.Persistence.Database/Repositories/ChangeLogRepository.cs similarity index 96% rename from DD.Persistence.Database.Postgres/Repositories/ChangeLogRepository.cs rename to DD.Persistence.Database/Repositories/ChangeLogRepository.cs index c2502ef..61e907d 100644 --- a/DD.Persistence.Database.Postgres/Repositories/ChangeLogRepository.cs +++ b/DD.Persistence.Database/Repositories/ChangeLogRepository.cs @@ -8,7 +8,7 @@ using Mapster; using Microsoft.EntityFrameworkCore; using UuidExtensions; -namespace DD.Persistence.Database.Postgres.Repositories; +namespace DD.Persistence.Database.Repositories; public class ChangeLogRepository : IChangeLogRepository { private readonly DbContext db; @@ -186,7 +186,7 @@ public class ChangeLogRepository : IChangeLogRepository var datesUpdate = await datesUpdateQuery.ToArrayAsync(token); - var dates = Enumerable.Concat(datesCreate, datesUpdate); + var dates = datesCreate.Concat(datesUpdate); var datesOnly = dates .Select(d => new DateOnly(d.Year, d.Month, d.Day)) .Distinct() @@ -214,7 +214,7 @@ public class ChangeLogRepository : IChangeLogRepository public async Task> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token) { var date = dateBegin.ToUniversalTime(); - var query = this.db.Set() + var query = db.Set() .Where(e => e.IdDiscriminator == idDiscriminator) .Where(e => e.Creation >= date || e.Obsolete >= date); @@ -233,7 +233,7 @@ public class ChangeLogRepository : IChangeLogRepository .Select(group => new { Min = group.Min(e => e.Creation), - Max = group.Max(e => (e.Obsolete.HasValue && e.Obsolete > e.Creation) + Max = group.Max(e => e.Obsolete.HasValue && e.Obsolete > e.Creation ? e.Obsolete.Value : e.Creation), }); diff --git a/DD.Persistence.Database.Postgres/Repositories/DataSchemeRepository.cs b/DD.Persistence.Database/Repositories/DataSchemeRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/Repositories/DataSchemeRepository.cs rename to DD.Persistence.Database/Repositories/DataSchemeRepository.cs diff --git a/DD.Persistence.Database.Postgres/Repositories/DataSourceSystemRepository.cs b/DD.Persistence.Database/Repositories/DataSourceSystemRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/Repositories/DataSourceSystemRepository.cs rename to DD.Persistence.Database/Repositories/DataSourceSystemRepository.cs diff --git a/DD.Persistence.Database.Postgres/Repositories/ParameterRepository.cs b/DD.Persistence.Database/Repositories/ParameterRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/Repositories/ParameterRepository.cs rename to DD.Persistence.Database/Repositories/ParameterRepository.cs diff --git a/DD.Persistence.Database.Postgres/Repositories/SetpointRepository.cs b/DD.Persistence.Database/Repositories/SetpointRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/Repositories/SetpointRepository.cs rename to DD.Persistence.Database/Repositories/SetpointRepository.cs diff --git a/DD.Persistence.Database.Postgres/Repositories/TechMessagesRepository.cs b/DD.Persistence.Database/Repositories/TechMessagesRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/Repositories/TechMessagesRepository.cs rename to DD.Persistence.Database/Repositories/TechMessagesRepository.cs diff --git a/DD.Persistence.Database.Postgres/Repositories/TimestampedValuesRepository.cs b/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/Repositories/TimestampedValuesRepository.cs rename to DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs diff --git a/DD.Persistence.Database.Postgres/RepositoriesCached/DataSchemeCachedRepository.cs b/DD.Persistence.Database/RepositoriesCached/DataSchemeCachedRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/RepositoriesCached/DataSchemeCachedRepository.cs rename to DD.Persistence.Database/RepositoriesCached/DataSchemeCachedRepository.cs diff --git a/DD.Persistence.Database.Postgres/RepositoriesCached/DataSourceSystemCachedRepository.cs b/DD.Persistence.Database/RepositoriesCached/DataSourceSystemCachedRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/RepositoriesCached/DataSourceSystemCachedRepository.cs rename to DD.Persistence.Database/RepositoriesCached/DataSourceSystemCachedRepository.cs diff --git a/DD.Persistence.Database.Postgres/RepositoriesCached/TimestampedValuesCachedRepository.cs b/DD.Persistence.Database/RepositoriesCached/TimestampedValuesCachedRepository.cs similarity index 100% rename from DD.Persistence.Database.Postgres/RepositoriesCached/TimestampedValuesCachedRepository.cs rename to DD.Persistence.Database/RepositoriesCached/TimestampedValuesCachedRepository.cs From 431c7278cb7ff63c66c764739617515c47cbbda4 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Wed, 5 Feb 2025 14:30:36 +0500 Subject: [PATCH 2/3] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20#1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DD.Persistence.Database/Entity/DataScheme.cs | 23 +++++++++++-------- .../TimestampedValuesRepository.cs | 9 -------- .../Services/TimestampedValuesService.cs | 3 +++ 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/DD.Persistence.Database/Entity/DataScheme.cs b/DD.Persistence.Database/Entity/DataScheme.cs index a231580..3ce46a2 100644 --- a/DD.Persistence.Database/Entity/DataScheme.cs +++ b/DD.Persistence.Database/Entity/DataScheme.cs @@ -1,19 +1,22 @@ -using DD.Persistence.Models; -using Microsoft.EntityFrameworkCore; -using System.ComponentModel.DataAnnotations; +using Microsoft.EntityFrameworkCore; using System.ComponentModel.DataAnnotations.Schema; +using System.Text.Json; namespace DD.Persistence.Database.Entity; -[Table("data_scheme")] -public class DataScheme +[Table("prop_scheme")] +[PrimaryKey(nameof(DiscriminatorId), nameof(Index))] +public class PropScheme { - [Key, Comment("Идентификатор схемы данных"),] + [Comment("Идентификатор схемы данных")] public Guid DiscriminatorId { get; set; } - [Comment("Наименования полей в порядке индексации"), Column(TypeName = "jsonb")] - public string[] PropNames { get; set; } = []; + [Comment("Индекс поля")] + public int Index { get; set; } - [Comment("Типы полей в порядке индексации")] - public PropTypeEnum[] PropTypes { get; set; } = []; + [Comment("Наименования индексируемого поля")] + public required string PropName { get; set; } + + [Comment("Тип индексируемого поля")] + public required JsonValueKind PropKind { get; set; } } diff --git a/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs b/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs index 149e411..1239b4a 100644 --- a/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs +++ b/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs @@ -55,15 +55,6 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository .Select(g => KeyValuePair.Create(g.Key, g.OrderBy(i => i.Timestamp).Skip(skip).Take(take))); var entities = await groupQuery.ToArrayAsync(token); - //var root = new TVertex( - // OperationEnum.And, - // new TLeaf(OperationEnum.Equal, "A", 1), - // new TLeaf(OperationEnum.Equal, "B", 1) - //); - //var dataScheme = entities.First().Value.First().DataScheme; - //var specification = dataScheme.BuildFilter(root); - //var que = ApplySpecification(specification); - var result = entities.ToDictionary(k => k.Key, v => v.Value.Select(e => ( e.Timestamp, e.Values diff --git a/DD.Persistence/Services/TimestampedValuesService.cs b/DD.Persistence/Services/TimestampedValuesService.cs index fc17777..264fdc5 100644 --- a/DD.Persistence/Services/TimestampedValuesService.cs +++ b/DD.Persistence/Services/TimestampedValuesService.cs @@ -2,6 +2,7 @@ using DD.Persistence.Models; using DD.Persistence.Repositories; using DD.Persistence.Services.Interfaces; +using System.Text.Json; namespace DD.Persistence.Services; @@ -100,6 +101,7 @@ public class TimestampedValuesService : ITimestampedValuesService return dtos; } + // ToDo: рефакторинг, переименовать (текущее название не отражает суть) /// /// Преобразовать результат запроса в набор dto /// @@ -183,6 +185,7 @@ public class TimestampedValuesService : ITimestampedValuesService { var types = dto.Values.Select(e => { + var objectKind = ((JsonElement) e.Value).ValueKind; var valueString = e.Value.ToString(); if (valueString is null) From 9ca49cb1b517355b74d2d7fcece2bb227f60cb36 Mon Sep 17 00:00:00 2001 From: Roman Efremov Date: Wed, 5 Feb 2025 17:20:18 +0500 Subject: [PATCH 3/3] =?UTF-8?q?=D0=9F=D1=80=D0=B0=D0=B2=D0=BA=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=BE=20=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20#2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DD.Persistence.API/Startup.cs | 2 +- ...ner.cs => 20250205114037_Init.Designer.cs} | 59 ++++++------- ...4044050_Init.cs => 20250205114037_Init.cs} | 39 ++++----- ...PersistencePostgresContextModelSnapshot.cs | 57 ++++++------ .../DependencyInjection.cs | 9 +- .../{DataScheme.cs => SchemeProperty.cs} | 9 +- .../Entity/TimestampedValues.cs | 3 - .../PersistenceDbContext.cs | 6 +- .../Repositories/DataSchemeRepository.cs | 34 -------- .../Repositories/SchemePropertyRepository.cs | 43 ++++++++++ .../TimestampedValuesRepository.cs | 3 +- ...y.cs => SchemePropertyCachedRepository.cs} | 12 +-- .../TimestampedValuesControllerTest.cs | 6 +- DD.Persistence.Models/DataSchemeDto.cs | 36 ++++++-- .../Enumerations/PropTypeEnum.cs | 14 --- DD.Persistence.Models/SchemePropertyDto.cs | 30 +++++++ .../TimestampedValuesServiceShould.cs | 2 +- ...sitory.cs => ISchemePropertyRepository.cs} | 4 +- .../Services/TimestampedValuesService.cs | 86 ++++++------------- 19 files changed, 221 insertions(+), 233 deletions(-) rename DD.Persistence.Database.Postgres/Migrations/{20250204044050_Init.Designer.cs => 20250205114037_Init.Designer.cs} (88%) rename DD.Persistence.Database.Postgres/Migrations/{20250204044050_Init.cs => 20250205114037_Init.cs} (90%) rename DD.Persistence.Database/Entity/{DataScheme.cs => SchemeProperty.cs} (71%) delete mode 100644 DD.Persistence.Database/Repositories/DataSchemeRepository.cs create mode 100644 DD.Persistence.Database/Repositories/SchemePropertyRepository.cs rename DD.Persistence.Database/RepositoriesCached/{DataSchemeCachedRepository.cs => SchemePropertyCachedRepository.cs} (57%) delete mode 100644 DD.Persistence.Models/Enumerations/PropTypeEnum.cs create mode 100644 DD.Persistence.Models/SchemePropertyDto.cs rename DD.Persistence/Repositories/{IDataSchemeRepository.cs => ISchemePropertyRepository.cs} (84%) diff --git a/DD.Persistence.API/Startup.cs b/DD.Persistence.API/Startup.cs index a3c3efe..f19e6cf 100644 --- a/DD.Persistence.API/Startup.cs +++ b/DD.Persistence.API/Startup.cs @@ -14,7 +14,7 @@ public class Startup public void ConfigureServices(IServiceCollection services) { - // Add services to the container. + // AddRange services to the container. services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle diff --git a/DD.Persistence.Database.Postgres/Migrations/20250204044050_Init.Designer.cs b/DD.Persistence.Database.Postgres/Migrations/20250205114037_Init.Designer.cs similarity index 88% rename from DD.Persistence.Database.Postgres/Migrations/20250204044050_Init.Designer.cs rename to DD.Persistence.Database.Postgres/Migrations/20250205114037_Init.Designer.cs index 60e6e92..b90d452 100644 --- a/DD.Persistence.Database.Postgres/Migrations/20250204044050_Init.Designer.cs +++ b/DD.Persistence.Database.Postgres/Migrations/20250205114037_Init.Designer.cs @@ -13,7 +13,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; namespace DD.Persistence.Database.Postgres.Migrations { [DbContext(typeof(PersistencePostgresContext))] - [Migration("20250204044050_Init")] + [Migration("20250205114037_Init")] partial class Init { /// @@ -67,28 +67,6 @@ namespace DD.Persistence.Database.Postgres.Migrations b.ToTable("change_log"); }); - modelBuilder.Entity("DD.Persistence.Database.Entity.DataScheme", b => - { - b.Property("DiscriminatorId") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasComment("Идентификатор схемы данных"); - - b.Property("PropNames") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("Наименования полей в порядке индексации"); - - b.PrimitiveCollection("PropTypes") - .IsRequired() - .HasColumnType("integer[]") - .HasComment("Типы полей в порядке индексации"); - - b.HasKey("DiscriminatorId"); - - b.ToTable("data_scheme"); - }); - modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b => { b.Property("SystemId") @@ -134,6 +112,30 @@ namespace DD.Persistence.Database.Postgres.Migrations b.ToTable("parameter_data"); }); + modelBuilder.Entity("DD.Persistence.Database.Entity.SchemeProperty", b => + { + b.Property("DiscriminatorId") + .HasColumnType("uuid") + .HasComment("Идентификатор схемы данных"); + + b.Property("Index") + .HasColumnType("integer") + .HasComment("Индекс поля"); + + b.Property("PropertyKind") + .HasColumnType("smallint") + .HasComment("Тип индексируемого поля"); + + b.Property("PropertyName") + .IsRequired() + .HasColumnType("text") + .HasComment("Наименования индексируемого поля"); + + b.HasKey("DiscriminatorId", "Index"); + + b.ToTable("scheme_property"); + }); + modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b => { b.Property("Key") @@ -222,17 +224,6 @@ namespace DD.Persistence.Database.Postgres.Migrations b.Navigation("System"); }); - - modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedValues", b => - { - b.HasOne("DD.Persistence.Database.Entity.DataScheme", "DataScheme") - .WithMany() - .HasForeignKey("DiscriminatorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("DataScheme"); - }); #pragma warning restore 612, 618 } } diff --git a/DD.Persistence.Database.Postgres/Migrations/20250204044050_Init.cs b/DD.Persistence.Database.Postgres/Migrations/20250205114037_Init.cs similarity index 90% rename from DD.Persistence.Database.Postgres/Migrations/20250204044050_Init.cs rename to DD.Persistence.Database.Postgres/Migrations/20250205114037_Init.cs index 24a310d..c872547 100644 --- a/DD.Persistence.Database.Postgres/Migrations/20250204044050_Init.cs +++ b/DD.Persistence.Database.Postgres/Migrations/20250205114037_Init.cs @@ -30,19 +30,6 @@ namespace DD.Persistence.Database.Postgres.Migrations table.PrimaryKey("PK_change_log", x => x.Id); }); - migrationBuilder.CreateTable( - name: "data_scheme", - columns: table => new - { - DiscriminatorId = table.Column(type: "uuid", nullable: false, comment: "Идентификатор схемы данных"), - PropNames = table.Column(type: "jsonb", nullable: false, comment: "Наименования полей в порядке индексации"), - PropTypes = table.Column(type: "integer[]", nullable: false, comment: "Типы полей в порядке индексации") - }, - constraints: table => - { - table.PrimaryKey("PK_data_scheme", x => x.DiscriminatorId); - }); - migrationBuilder.CreateTable( name: "data_source_system", columns: table => new @@ -70,6 +57,20 @@ namespace DD.Persistence.Database.Postgres.Migrations table.PrimaryKey("PK_parameter_data", x => new { x.DiscriminatorId, x.ParameterId, x.Timestamp }); }); + migrationBuilder.CreateTable( + name: "scheme_property", + columns: table => new + { + DiscriminatorId = table.Column(type: "uuid", nullable: false, comment: "Идентификатор схемы данных"), + Index = table.Column(type: "integer", nullable: false, comment: "Индекс поля"), + PropertyName = table.Column(type: "text", nullable: false, comment: "Наименования индексируемого поля"), + PropertyKind = table.Column(type: "smallint", nullable: false, comment: "Тип индексируемого поля") + }, + constraints: table => + { + table.PrimaryKey("PK_scheme_property", x => new { x.DiscriminatorId, x.Index }); + }); + migrationBuilder.CreateTable( name: "setpoint", columns: table => new @@ -95,12 +96,6 @@ namespace DD.Persistence.Database.Postgres.Migrations constraints: table => { table.PrimaryKey("PK_timestamped_values", x => new { x.DiscriminatorId, x.Timestamp }); - table.ForeignKey( - name: "FK_timestamped_values_data_scheme_DiscriminatorId", - column: x => x.DiscriminatorId, - principalTable: "data_scheme", - principalColumn: "DiscriminatorId", - onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -140,6 +135,9 @@ namespace DD.Persistence.Database.Postgres.Migrations migrationBuilder.DropTable( name: "parameter_data"); + migrationBuilder.DropTable( + name: "scheme_property"); + migrationBuilder.DropTable( name: "setpoint"); @@ -151,9 +149,6 @@ namespace DD.Persistence.Database.Postgres.Migrations migrationBuilder.DropTable( name: "data_source_system"); - - migrationBuilder.DropTable( - name: "data_scheme"); } } } diff --git a/DD.Persistence.Database.Postgres/Migrations/PersistencePostgresContextModelSnapshot.cs b/DD.Persistence.Database.Postgres/Migrations/PersistencePostgresContextModelSnapshot.cs index ca319a5..e2b0921 100644 --- a/DD.Persistence.Database.Postgres/Migrations/PersistencePostgresContextModelSnapshot.cs +++ b/DD.Persistence.Database.Postgres/Migrations/PersistencePostgresContextModelSnapshot.cs @@ -64,28 +64,6 @@ namespace DD.Persistence.Database.Postgres.Migrations b.ToTable("change_log"); }); - modelBuilder.Entity("DD.Persistence.Database.Entity.DataScheme", b => - { - b.Property("DiscriminatorId") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasComment("Идентификатор схемы данных"); - - b.Property("PropNames") - .IsRequired() - .HasColumnType("jsonb") - .HasComment("Наименования полей в порядке индексации"); - - b.PrimitiveCollection("PropTypes") - .IsRequired() - .HasColumnType("integer[]") - .HasComment("Типы полей в порядке индексации"); - - b.HasKey("DiscriminatorId"); - - b.ToTable("data_scheme"); - }); - modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b => { b.Property("SystemId") @@ -131,6 +109,30 @@ namespace DD.Persistence.Database.Postgres.Migrations b.ToTable("parameter_data"); }); + modelBuilder.Entity("DD.Persistence.Database.Entity.SchemeProperty", b => + { + b.Property("DiscriminatorId") + .HasColumnType("uuid") + .HasComment("Идентификатор схемы данных"); + + b.Property("Index") + .HasColumnType("integer") + .HasComment("Индекс поля"); + + b.Property("PropertyKind") + .HasColumnType("smallint") + .HasComment("Тип индексируемого поля"); + + b.Property("PropertyName") + .IsRequired() + .HasColumnType("text") + .HasComment("Наименования индексируемого поля"); + + b.HasKey("DiscriminatorId", "Index"); + + b.ToTable("scheme_property"); + }); + modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b => { b.Property("Key") @@ -219,17 +221,6 @@ namespace DD.Persistence.Database.Postgres.Migrations b.Navigation("System"); }); - - modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedValues", b => - { - b.HasOne("DD.Persistence.Database.Entity.DataScheme", "DataScheme") - .WithMany() - .HasForeignKey("DiscriminatorId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("DataScheme"); - }); #pragma warning restore 612, 618 } } diff --git a/DD.Persistence.Database/DependencyInjection.cs b/DD.Persistence.Database/DependencyInjection.cs index c04d9e5..ca140d8 100644 --- a/DD.Persistence.Database/DependencyInjection.cs +++ b/DD.Persistence.Database/DependencyInjection.cs @@ -2,6 +2,7 @@ using DD.Persistence.Database.Postgres.Repositories; using DD.Persistence.Database.Postgres.RepositoriesCached; using DD.Persistence.Database.Repositories; +using DD.Persistence.Database.RepositoriesCached; using DD.Persistence.Models; using DD.Persistence.Repositories; using Mapster; @@ -24,6 +25,12 @@ public static class DependencyInjection Value = src.Value, Id = src.Id }); + + TypeAdapterConfig, SchemeProperty>.NewConfig() + .Map(dest => dest.DiscriminatorId, src => src.Key) + .Map(dest => dest.Index, src => src.Value.Index) + .Map(dest => dest.PropertyKind, src => src.Value.PropertyKind) + .Map(dest => dest.PropertyName, src => src.Value.PropertyName); } public static IServiceCollection AddInfrastructure(this IServiceCollection services) @@ -40,7 +47,7 @@ public static class DependencyInjection services.AddTransient(); services.AddTransient(); services.AddTransient(); - services.AddTransient(); + services.AddTransient(); return services; } diff --git a/DD.Persistence.Database/Entity/DataScheme.cs b/DD.Persistence.Database/Entity/SchemeProperty.cs similarity index 71% rename from DD.Persistence.Database/Entity/DataScheme.cs rename to DD.Persistence.Database/Entity/SchemeProperty.cs index 3ce46a2..6ef5bdb 100644 --- a/DD.Persistence.Database/Entity/DataScheme.cs +++ b/DD.Persistence.Database/Entity/SchemeProperty.cs @@ -1,12 +1,13 @@ using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Text.Json; namespace DD.Persistence.Database.Entity; -[Table("prop_scheme")] +[Table("scheme_property")] [PrimaryKey(nameof(DiscriminatorId), nameof(Index))] -public class PropScheme +public class SchemeProperty { [Comment("Идентификатор схемы данных")] public Guid DiscriminatorId { get; set; } @@ -15,8 +16,8 @@ public class PropScheme public int Index { get; set; } [Comment("Наименования индексируемого поля")] - public required string PropName { get; set; } + public required string PropertyName { get; set; } [Comment("Тип индексируемого поля")] - public required JsonValueKind PropKind { get; set; } + public required JsonValueKind PropertyKind { get; set; } } diff --git a/DD.Persistence.Database/Entity/TimestampedValues.cs b/DD.Persistence.Database/Entity/TimestampedValues.cs index a2835f7..d28e1cf 100644 --- a/DD.Persistence.Database/Entity/TimestampedValues.cs +++ b/DD.Persistence.Database/Entity/TimestampedValues.cs @@ -17,7 +17,4 @@ public class TimestampedValues : ITimestampedItem [Comment("Данные"), Column(TypeName = "jsonb")] public required object[] Values { get; set; } - - [Required, ForeignKey(nameof(DiscriminatorId)), Comment("Идентификаторы")] - public virtual DataScheme? DataScheme { get; set; } } diff --git a/DD.Persistence.Database/PersistenceDbContext.cs b/DD.Persistence.Database/PersistenceDbContext.cs index fbbc057..4b0a874 100644 --- a/DD.Persistence.Database/PersistenceDbContext.cs +++ b/DD.Persistence.Database/PersistenceDbContext.cs @@ -10,7 +10,7 @@ public class PersistenceDbContext : DbContext { public DbSet Setpoint => Set(); - public DbSet DataSchemes => Set(); + public DbSet SchemeProperty => Set(); public DbSet TimestampedValues => Set(); @@ -30,10 +30,6 @@ public class PersistenceDbContext : DbContext protected override void OnModelCreating(ModelBuilder modelBuilder) { - modelBuilder.Entity() - .Property(e => e.PropNames) - .HasJsonConversion(); - modelBuilder.Entity() .Property(e => e.Values) .HasJsonConversion(); diff --git a/DD.Persistence.Database/Repositories/DataSchemeRepository.cs b/DD.Persistence.Database/Repositories/DataSchemeRepository.cs deleted file mode 100644 index ba5ccd7..0000000 --- a/DD.Persistence.Database/Repositories/DataSchemeRepository.cs +++ /dev/null @@ -1,34 +0,0 @@ -using DD.Persistence.Database.Entity; -using DD.Persistence.Models; -using DD.Persistence.Repositories; -using Mapster; -using Microsoft.EntityFrameworkCore; - -namespace DD.Persistence.Database.Postgres.Repositories; -public class DataSchemeRepository : IDataSchemeRepository -{ - protected DbContext db; - public DataSchemeRepository(DbContext db) - { - this.db = db; - } - protected virtual IQueryable GetQueryReadOnly() => db.Set(); - - public virtual async Task Add(DataSchemeDto dataSourceSystemDto, CancellationToken token) - { - var entity = dataSourceSystemDto.Adapt(); - - await db.Set().AddAsync(entity, token); - await db.SaveChangesAsync(token); - } - - public virtual async Task Get(Guid dataSchemeId, CancellationToken token) - { - var query = GetQueryReadOnly() - .Where(e => e.DiscriminatorId == dataSchemeId); - var entity = await query.ToArrayAsync(); - var dto = entity.Select(e => e.Adapt()).FirstOrDefault(); - - return dto; - } -} diff --git a/DD.Persistence.Database/Repositories/SchemePropertyRepository.cs b/DD.Persistence.Database/Repositories/SchemePropertyRepository.cs new file mode 100644 index 0000000..26bb8aa --- /dev/null +++ b/DD.Persistence.Database/Repositories/SchemePropertyRepository.cs @@ -0,0 +1,43 @@ +using DD.Persistence.Database.Entity; +using DD.Persistence.Models; +using DD.Persistence.Repositories; +using Mapster; +using Microsoft.EntityFrameworkCore; + +namespace DD.Persistence.Database.Repositories; +public class SchemePropertyRepository : ISchemePropertyRepository +{ + protected DbContext db; + public SchemePropertyRepository(DbContext db) + { + this.db = db; + } + protected virtual IQueryable GetQueryReadOnly() => db.Set(); + + public virtual async Task AddRange(DataSchemeDto dataSchemeDto, CancellationToken token) + { + var entities = dataSchemeDto.Select(e => + KeyValuePair.Create(dataSchemeDto.DiscriminatorId, e) + .Adapt() + ); + + await db.Set().AddRangeAsync(entities, token); + await db.SaveChangesAsync(token); + } + + public virtual async Task Get(Guid dataSchemeId, CancellationToken token) + { + var query = GetQueryReadOnly() + .Where(e => e.DiscriminatorId == dataSchemeId); + var entities = await query.ToArrayAsync(token); + + DataSchemeDto? result = null; + if (entities.Length != 0) + { + var properties = entities.Select(e => e.Adapt()).ToArray(); + result = new DataSchemeDto(dataSchemeId, properties); + } + + return result; + } +} diff --git a/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs b/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs index 1239b4a..5f3f60e 100644 --- a/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs +++ b/DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs @@ -14,8 +14,7 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository this.db = db; } - protected virtual IQueryable GetQueryReadOnly() => this.db.Set() - .Include(e => e.DataScheme); + protected virtual IQueryable GetQueryReadOnly() => this.db.Set(); public async virtual Task AddRange(Guid discriminatorId, IEnumerable dtos, CancellationToken token) { diff --git a/DD.Persistence.Database/RepositoriesCached/DataSchemeCachedRepository.cs b/DD.Persistence.Database/RepositoriesCached/SchemePropertyCachedRepository.cs similarity index 57% rename from DD.Persistence.Database/RepositoriesCached/DataSchemeCachedRepository.cs rename to DD.Persistence.Database/RepositoriesCached/SchemePropertyCachedRepository.cs index f4cec62..64d9c01 100644 --- a/DD.Persistence.Database/RepositoriesCached/DataSchemeCachedRepository.cs +++ b/DD.Persistence.Database/RepositoriesCached/SchemePropertyCachedRepository.cs @@ -1,21 +1,21 @@ using DD.Persistence.Models; -using DD.Persistence.Database.Postgres.Repositories; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; +using DD.Persistence.Database.Repositories; -namespace DD.Persistence.Database.Postgres.RepositoriesCached; -public class DataSchemeCachedRepository : DataSchemeRepository +namespace DD.Persistence.Database.RepositoriesCached; +public class SchemePropertyCachedRepository : SchemePropertyRepository { private readonly IMemoryCache memoryCache; - public DataSchemeCachedRepository(DbContext db, IMemoryCache memoryCache) : base(db) + public SchemePropertyCachedRepository(DbContext db, IMemoryCache memoryCache) : base(db) { this.memoryCache = memoryCache; } - public override async Task Add(DataSchemeDto dataSourceSystemDto, CancellationToken token) + public override async Task AddRange(DataSchemeDto dataSourceSystemDto, CancellationToken token) { - await base.Add(dataSourceSystemDto, token); + await base.AddRange(dataSourceSystemDto, token); memoryCache.Set(dataSourceSystemDto.DiscriminatorId, dataSourceSystemDto); } diff --git a/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs b/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs index 526b372..9bb1d58 100644 --- a/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs +++ b/DD.Persistence.IntegrationTests/Controllers/TimestampedValuesControllerTest.cs @@ -406,8 +406,12 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest private void Cleanup() { + foreach (var item in discriminatorIds) + { + memoryCache.Remove(item); + } discriminatorIds = []; dbContext.CleanupDbSet(); - dbContext.CleanupDbSet(); + dbContext.CleanupDbSet(); } } diff --git a/DD.Persistence.Models/DataSchemeDto.cs b/DD.Persistence.Models/DataSchemeDto.cs index 7f238aa..d20ffaa 100644 --- a/DD.Persistence.Models/DataSchemeDto.cs +++ b/DD.Persistence.Models/DataSchemeDto.cs @@ -1,9 +1,11 @@ -namespace DD.Persistence.Models; +using System.Collections; + +namespace DD.Persistence.Models; /// /// Схема для набора данных /// -public class DataSchemeDto +public class DataSchemeDto : IEnumerable, IEquatable> { /// /// Дискриминатор @@ -11,12 +13,30 @@ public class DataSchemeDto public Guid DiscriminatorId { get; set; } /// - /// Наименования полей + /// Поля /// - public string[] PropNames { get; set; } = []; + private IEnumerable Properties { get; } = []; - /// - /// Типы полей - /// - public PropTypeEnum[] PropTypes { get; set; } = []; + /// + public DataSchemeDto(Guid discriminatorId, SchemePropertyDto[] Properties) + { + DiscriminatorId = discriminatorId; + this.Properties = Properties; + } + + /// + public IEnumerator GetEnumerator() + => Properties.GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + /// + public bool Equals(IEnumerable? otherProperties) + { + //if (otherProperties is null) + // return false; + + return Properties.SequenceEqual(otherProperties); + } } diff --git a/DD.Persistence.Models/Enumerations/PropTypeEnum.cs b/DD.Persistence.Models/Enumerations/PropTypeEnum.cs deleted file mode 100644 index 5379929..0000000 --- a/DD.Persistence.Models/Enumerations/PropTypeEnum.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace DD.Persistence.Models; - -/// -/// Типы для набора данных -/// -public enum PropTypeEnum -{ - /// - String = 0, - /// - Double = 1, - /// - DateTime = 2 -} diff --git a/DD.Persistence.Models/SchemePropertyDto.cs b/DD.Persistence.Models/SchemePropertyDto.cs new file mode 100644 index 0000000..0c34ba7 --- /dev/null +++ b/DD.Persistence.Models/SchemePropertyDto.cs @@ -0,0 +1,30 @@ +using System.Text.Json; + +namespace DD.Persistence.Models; + +/// +/// Индексируемого поле из схемы для набора данных +/// +public class SchemePropertyDto : IEquatable +{ + /// + /// Индекс поля + /// + public required int Index { get; set; } + + /// + /// Наименование индексируемого поля + /// + public required string PropertyName { get; set; } + + /// + /// Тип индексируемого поля + /// + public required JsonValueKind PropertyKind { get; set; } + + /// + public bool Equals(SchemePropertyDto? other) + { + return Index == other?.Index && PropertyName == other?.PropertyName && PropertyKind == other?.PropertyKind; + } +} diff --git a/DD.Persistence.Test/TimestampedValuesServiceShould.cs b/DD.Persistence.Test/TimestampedValuesServiceShould.cs index 0acb6de..ad26d14 100644 --- a/DD.Persistence.Test/TimestampedValuesServiceShould.cs +++ b/DD.Persistence.Test/TimestampedValuesServiceShould.cs @@ -7,7 +7,7 @@ namespace DD.Persistence.Repository.Test; public class TimestampedValuesServiceShould { private readonly ITimestampedValuesRepository timestampedValuesRepository = Substitute.For(); - private readonly IDataSchemeRepository dataSchemeRepository = Substitute.For(); + private readonly ISchemePropertyRepository dataSchemeRepository = Substitute.For(); private TimestampedValuesService timestampedValuesService; public TimestampedValuesServiceShould() diff --git a/DD.Persistence/Repositories/IDataSchemeRepository.cs b/DD.Persistence/Repositories/ISchemePropertyRepository.cs similarity index 84% rename from DD.Persistence/Repositories/IDataSchemeRepository.cs rename to DD.Persistence/Repositories/ISchemePropertyRepository.cs index c14a9cf..458f5cd 100644 --- a/DD.Persistence/Repositories/IDataSchemeRepository.cs +++ b/DD.Persistence/Repositories/ISchemePropertyRepository.cs @@ -5,7 +5,7 @@ namespace DD.Persistence.Repositories; /// /// Репозиторий для работы со схемами наборов данных /// -public interface IDataSchemeRepository +public interface ISchemePropertyRepository { /// /// Добавить схему @@ -13,7 +13,7 @@ public interface IDataSchemeRepository /// /// /// - Task Add(DataSchemeDto dataSourceSystemDto, CancellationToken token); + Task AddRange(DataSchemeDto dataSourceSystemDto, CancellationToken token); /// /// Вычитать схему diff --git a/DD.Persistence/Services/TimestampedValuesService.cs b/DD.Persistence/Services/TimestampedValuesService.cs index 264fdc5..5e6f9ed 100644 --- a/DD.Persistence/Services/TimestampedValuesService.cs +++ b/DD.Persistence/Services/TimestampedValuesService.cs @@ -10,10 +10,10 @@ namespace DD.Persistence.Services; public class TimestampedValuesService : ITimestampedValuesService { private readonly ITimestampedValuesRepository timestampedValuesRepository; - private readonly IDataSchemeRepository dataSchemeRepository; + private readonly ISchemePropertyRepository dataSchemeRepository; /// - public TimestampedValuesService(ITimestampedValuesRepository timestampedValuesRepository, IDataSchemeRepository relatedDataRepository) + public TimestampedValuesService(ITimestampedValuesRepository timestampedValuesRepository, ISchemePropertyRepository relatedDataRepository) { this.timestampedValuesRepository = timestampedValuesRepository; this.dataSchemeRepository = relatedDataRepository; @@ -38,7 +38,7 @@ public class TimestampedValuesService : ITimestampedValuesService { var result = await timestampedValuesRepository.Get(discriminatorIds, geTimestamp, columnNames, skip, take, token); - var dtos = await Materialize(result, token); + var dtos = await BindingToDataScheme(result, token); if (!columnNames.IsNullOrEmpty()) { @@ -53,9 +53,9 @@ public class TimestampedValuesService : ITimestampedValuesService { var result = await timestampedValuesRepository.GetFirst(discriminatorId, takeCount, token); - var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) } + var resultBeforeBinding = new[] { KeyValuePair.Create(discriminatorId, result) } .ToDictionary(); - var dtos = await Materialize(resultToMaterialize, token); + var dtos = await BindingToDataScheme(resultBeforeBinding, token); return dtos; } @@ -65,9 +65,9 @@ public class TimestampedValuesService : ITimestampedValuesService { var result = await timestampedValuesRepository.GetLast(discriminatorId, takeCount, token); - var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) } + var resultBeforeBinding = new[] { KeyValuePair.Create(discriminatorId, result) } .ToDictionary(); - var dtos = await Materialize(resultToMaterialize, token); + var dtos = await BindingToDataScheme(resultBeforeBinding, token); return dtos; } @@ -82,9 +82,9 @@ public class TimestampedValuesService : ITimestampedValuesService { var result = await timestampedValuesRepository.GetResampledData(discriminatorId, beginTimestamp, intervalSec, approxPointsCount, token); - var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) } + var resultBeforeBinding = new[] { KeyValuePair.Create(discriminatorId, result) } .ToDictionary(); - var dtos = await Materialize(resultToMaterialize, token); + var dtos = await BindingToDataScheme(resultBeforeBinding, token); return dtos; } @@ -94,9 +94,9 @@ public class TimestampedValuesService : ITimestampedValuesService { var result = await timestampedValuesRepository.GetGtDate(discriminatorId, beginTimestamp, token); - var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) } + var resultBeforeBinding = new[] { KeyValuePair.Create(discriminatorId, result) } .ToDictionary(); - var dtos = await Materialize(resultToMaterialize, token); + var dtos = await BindingToDataScheme(resultBeforeBinding, token); return dtos; } @@ -108,28 +108,22 @@ public class TimestampedValuesService : ITimestampedValuesService /// /// /// - private async Task> Materialize(IDictionary> queryResult, CancellationToken token) + private async Task> BindingToDataScheme(IDictionary> queryResult, CancellationToken token) { IEnumerable result = []; foreach (var keyValuePair in queryResult) { var dataScheme = await dataSchemeRepository.Get(keyValuePair.Key, token); if (dataScheme is null) - { continue; - } foreach (var tuple in keyValuePair.Value) { - var identity = dataScheme!.PropNames; - var indexedIdentity = identity - .Select((value, index) => new { index, value }); - var dto = new TimestampedValuesDto() { Timestamp = tuple.Timestamp.ToUniversalTime(), - Values = indexedIdentity - .ToDictionary(x => x.value, x => tuple.Values[x.index]) + Values = dataScheme + .ToDictionary(k => k.PropertyName, v => tuple.Values[v.Index]) }; result = result.Append(dto); @@ -149,61 +143,29 @@ public class TimestampedValuesService : ITimestampedValuesService /// Некорректный набор наименований полей private async Task CreateDataSchemeIfNotExist(Guid discriminatorId, TimestampedValuesDto dto, CancellationToken token) { - var propNames = dto.Values.Keys.ToArray(); - var propTypes = GetPropTypes(dto); + var valuesList = dto.Values.ToList(); + var properties = valuesList.ToList().Select(e => new SchemePropertyDto() { + Index = valuesList.IndexOf(e), + PropertyName = e.Key, + PropertyKind = ((JsonElement) e.Value).ValueKind + }).ToArray(); var dataScheme = await dataSchemeRepository.Get(discriminatorId, token); if (dataScheme is null) { - dataScheme = new DataSchemeDto() - { - DiscriminatorId = discriminatorId, - PropNames = propNames, - PropTypes = propTypes - }; - await dataSchemeRepository.Add(dataScheme, token); + dataScheme = new DataSchemeDto(discriminatorId, properties); + await dataSchemeRepository.AddRange(dataScheme, token); return; } - if (!dataScheme.PropNames.SequenceEqual(propNames)) + if (!dataScheme.Equals(properties)) { - var expectedFieldNames = string.Join(", ", dataScheme.PropNames); - var actualFieldNames = string.Join(", ", propNames); throw new InvalidOperationException($"Для системы {discriminatorId.ToString()} " + - $"характерен набор данных: [{expectedFieldNames}], однако был передан набор: [{actualFieldNames}]"); + $"был передан нехарактерный набор данных"); } } - /// - /// Получить типы для набора данных в соответствии с индексацией - /// - /// - /// - /// - private PropTypeEnum[] GetPropTypes(TimestampedValuesDto dto) - { - var types = dto.Values.Select(e => - { - var objectKind = ((JsonElement) e.Value).ValueKind; - var valueString = e.Value.ToString(); - - if (valueString is null) - throw new ArgumentNullException("Переданный набор данных содержит null, в следствии чего не удаётся определить типы полей"); - - if (DateTimeOffset.TryParse(valueString, out _)) - return PropTypeEnum.DateTime; - - var doubleString = valueString.Replace('.', ','); - if (double.TryParse(doubleString, out _)) - return PropTypeEnum.Double; - - return PropTypeEnum.String; - }); - - return types.ToArray(); - } - /// /// Отсеить лишние поля в соответствии с заданным фильтром ///