diff --git a/DD.Persistence.API/Startup.cs b/DD.Persistence.API/Startup.cs
index bc78548..f19e6cf 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;
@@ -13,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/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.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.Postgres/Repositories/DataSchemeRepository.cs b/DD.Persistence.Database.Postgres/Repositories/DataSchemeRepository.cs
deleted file mode 100644
index ba5ccd7..0000000
--- a/DD.Persistence.Database.Postgres/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/DD.Persistence.Database.csproj b/DD.Persistence.Database/DD.Persistence.Database.csproj
index 485a40b..4d751e4 100644
--- a/DD.Persistence.Database/DD.Persistence.Database.csproj
+++ b/DD.Persistence.Database/DD.Persistence.Database.csproj
@@ -1,4 +1,4 @@
-
+
net9.0
@@ -7,12 +7,12 @@
-
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..ca140d8
--- /dev/null
+++ b/DD.Persistence.Database/DependencyInjection.cs
@@ -0,0 +1,54 @@
+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.Database.RepositoriesCached;
+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
+ });
+
+ 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)
+ {
+ 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/Entity/DataScheme.cs b/DD.Persistence.Database/Entity/DataScheme.cs
deleted file mode 100644
index a231580..0000000
--- a/DD.Persistence.Database/Entity/DataScheme.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-using DD.Persistence.Models;
-using Microsoft.EntityFrameworkCore;
-using System.ComponentModel.DataAnnotations;
-using System.ComponentModel.DataAnnotations.Schema;
-
-namespace DD.Persistence.Database.Entity;
-
-[Table("data_scheme")]
-public class DataScheme
-{
- [Key, Comment("Идентификатор схемы данных"),]
- public Guid DiscriminatorId { get; set; }
-
- [Comment("Наименования полей в порядке индексации"), Column(TypeName = "jsonb")]
- public string[] PropNames { get; set; } = [];
-
- [Comment("Типы полей в порядке индексации")]
- public PropTypeEnum[] PropTypes { get; set; } = [];
-}
diff --git a/DD.Persistence.Database/Entity/SchemeProperty.cs b/DD.Persistence.Database/Entity/SchemeProperty.cs
new file mode 100644
index 0000000..6ef5bdb
--- /dev/null
+++ b/DD.Persistence.Database/Entity/SchemeProperty.cs
@@ -0,0 +1,23 @@
+using Microsoft.EntityFrameworkCore;
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using System.Text.Json;
+
+namespace DD.Persistence.Database.Entity;
+
+[Table("scheme_property")]
+[PrimaryKey(nameof(DiscriminatorId), nameof(Index))]
+public class SchemeProperty
+{
+ [Comment("Идентификатор схемы данных")]
+ public Guid DiscriminatorId { get; set; }
+
+ [Comment("Индекс поля")]
+ public int Index { get; set; }
+
+ [Comment("Наименования индексируемого поля")]
+ public required string PropertyName { get; set; }
+
+ [Comment("Тип индексируемого поля")]
+ public required JsonValueKind PropertyKind { get; set; }
+}
diff --git a/DD.Persistence.Database/Entity/TimestampedValues.cs b/DD.Persistence.Database/Entity/TimestampedValues.cs
index 84778c1..93acad9 100644
--- a/DD.Persistence.Database/Entity/TimestampedValues.cs
+++ b/DD.Persistence.Database/Entity/TimestampedValues.cs
@@ -17,7 +17,4 @@ public class TimestampedValues : ITimestampedItem, IValuesItem
[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.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/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.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/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/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.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 92%
rename from DD.Persistence.Database.Postgres/Repositories/TimestampedValuesRepository.cs
rename to DD.Persistence.Database/Repositories/TimestampedValuesRepository.cs
index 149e411..5f3f60e 100644
--- a/DD.Persistence.Database.Postgres/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)
{
@@ -55,15 +54,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.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/DataSchemeCachedRepository.cs b/DD.Persistence.Database/RepositoriesCached/SchemePropertyCachedRepository.cs
similarity index 57%
rename from DD.Persistence.Database.Postgres/RepositoriesCached/DataSchemeCachedRepository.cs
rename to DD.Persistence.Database/RepositoriesCached/SchemePropertyCachedRepository.cs
index f4cec62..64d9c01 100644
--- a/DD.Persistence.Database.Postgres/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.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
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 165d4e0..1a51eb1 100644
--- a/DD.Persistence.Test/TimestampedValuesServiceShould.cs
+++ b/DD.Persistence.Test/TimestampedValuesServiceShould.cs
@@ -1,4 +1,4 @@
-using DD.Persistence.Models;
+using DD.Persistence.Models;
using DD.Persistence.Repositories;
using DD.Persistence.Services;
using NSubstitute;
@@ -7,8 +7,8 @@ namespace DD.Persistence.Test;
public class TimestampedValuesServiceShould
{
private readonly ITimestampedValuesRepository timestampedValuesRepository = Substitute.For();
- private readonly IDataSchemeRepository dataSchemeRepository = Substitute.For();
- private readonly TimestampedValuesService timestampedValuesService;
+ 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 fc17777..5e6f9ed 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;
@@ -9,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;
@@ -37,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())
{
@@ -52,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;
}
@@ -64,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;
}
@@ -81,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;
}
@@ -93,41 +94,36 @@ 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;
}
+ // ToDo: рефакторинг, переименовать (текущее название не отражает суть)
///
/// Преобразовать результат запроса в набор dto
///
///
///
///
- 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);
@@ -147,60 +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 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();
- }
-
///
/// Отсеить лишние поля в соответствии с заданным фильтром
///