Merge branch 'RepositoriesRework' into FilterBuilder
This commit is contained in:
commit
5abfcc0d50
@ -1,4 +1,5 @@
|
|||||||
using DD.Persistence.Database.Model;
|
using DD.Persistence.Database;
|
||||||
|
using DD.Persistence.Database.Model;
|
||||||
using DD.Persistence.Database.Postgres.Extensions;
|
using DD.Persistence.Database.Postgres.Extensions;
|
||||||
|
|
||||||
namespace DD.Persistence.API;
|
namespace DD.Persistence.API;
|
||||||
@ -13,7 +14,7 @@ public class Startup
|
|||||||
|
|
||||||
public void ConfigureServices(IServiceCollection services)
|
public void ConfigureServices(IServiceCollection services)
|
||||||
{
|
{
|
||||||
// Add services to the container.
|
// AddRange services to the container.
|
||||||
|
|
||||||
services.AddControllers();
|
services.AddControllers();
|
||||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
|
@ -7,13 +7,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.2" />
|
||||||
<PackageReference Include="UuidExtensions" Version="1.2.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -24,37 +24,4 @@ public static class DependencyInjection
|
|||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void MapsterSetup()
|
|
||||||
{
|
|
||||||
TypeAdapterConfig.GlobalSettings.Default.Config
|
|
||||||
.ForType<TechMessageDto, TechMessage>()
|
|
||||||
.Ignore(dest => dest.System, dest => dest.SystemId);
|
|
||||||
|
|
||||||
TypeAdapterConfig<ChangeLog, ChangeLogDto>.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<ISetpointRepository, SetpointRepository>();
|
|
||||||
services.AddTransient<IChangeLogRepository, ChangeLogRepository>();
|
|
||||||
services.AddTransient<ITimestampedValuesRepository, TimestampedValuesRepository>();
|
|
||||||
services.AddTransient<ITechMessagesRepository, TechMessagesRepository>();
|
|
||||||
services.AddTransient<IParameterRepository, ParameterRepository>();
|
|
||||||
services.AddTransient<IDataSourceSystemRepository, DataSourceSystemCachedRepository>();
|
|
||||||
services.AddTransient<IDataSchemeRepository, DataSchemeCachedRepository>();
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|||||||
namespace DD.Persistence.Database.Postgres.Migrations
|
namespace DD.Persistence.Database.Postgres.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(PersistencePostgresContext))]
|
[DbContext(typeof(PersistencePostgresContext))]
|
||||||
[Migration("20250204044050_Init")]
|
[Migration("20250205114037_Init")]
|
||||||
partial class Init
|
partial class Init
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -67,28 +67,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
b.ToTable("change_log");
|
b.ToTable("change_log");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataScheme", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("DiscriminatorId")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid")
|
|
||||||
.HasComment("Идентификатор схемы данных");
|
|
||||||
|
|
||||||
b.Property<string>("PropNames")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
|
||||||
.HasComment("Наименования полей в порядке индексации");
|
|
||||||
|
|
||||||
b.PrimitiveCollection<int[]>("PropTypes")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("integer[]")
|
|
||||||
.HasComment("Типы полей в порядке индексации");
|
|
||||||
|
|
||||||
b.HasKey("DiscriminatorId");
|
|
||||||
|
|
||||||
b.ToTable("data_scheme");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("SystemId")
|
b.Property<Guid>("SystemId")
|
||||||
@ -134,6 +112,30 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
b.ToTable("parameter_data");
|
b.ToTable("parameter_data");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DD.Persistence.Database.Entity.SchemeProperty", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("DiscriminatorId")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasComment("Идентификатор схемы данных");
|
||||||
|
|
||||||
|
b.Property<int>("Index")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasComment("Индекс поля");
|
||||||
|
|
||||||
|
b.Property<byte>("PropertyKind")
|
||||||
|
.HasColumnType("smallint")
|
||||||
|
.HasComment("Тип индексируемого поля");
|
||||||
|
|
||||||
|
b.Property<string>("PropertyName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasComment("Наименования индексируемого поля");
|
||||||
|
|
||||||
|
b.HasKey("DiscriminatorId", "Index");
|
||||||
|
|
||||||
|
b.ToTable("scheme_property");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Key")
|
b.Property<Guid>("Key")
|
||||||
@ -222,17 +224,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.Navigation("System");
|
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
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,19 +30,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
table.PrimaryKey("PK_change_log", x => x.Id);
|
table.PrimaryKey("PK_change_log", x => x.Id);
|
||||||
});
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
|
||||||
name: "data_scheme",
|
|
||||||
columns: table => new
|
|
||||||
{
|
|
||||||
DiscriminatorId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Идентификатор схемы данных"),
|
|
||||||
PropNames = table.Column<string>(type: "jsonb", nullable: false, comment: "Наименования полей в порядке индексации"),
|
|
||||||
PropTypes = table.Column<int[]>(type: "integer[]", nullable: false, comment: "Типы полей в порядке индексации")
|
|
||||||
},
|
|
||||||
constraints: table =>
|
|
||||||
{
|
|
||||||
table.PrimaryKey("PK_data_scheme", x => x.DiscriminatorId);
|
|
||||||
});
|
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "data_source_system",
|
name: "data_source_system",
|
||||||
columns: table => new
|
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 });
|
table.PrimaryKey("PK_parameter_data", x => new { x.DiscriminatorId, x.ParameterId, x.Timestamp });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "scheme_property",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
DiscriminatorId = table.Column<Guid>(type: "uuid", nullable: false, comment: "Идентификатор схемы данных"),
|
||||||
|
Index = table.Column<int>(type: "integer", nullable: false, comment: "Индекс поля"),
|
||||||
|
PropertyName = table.Column<string>(type: "text", nullable: false, comment: "Наименования индексируемого поля"),
|
||||||
|
PropertyKind = table.Column<byte>(type: "smallint", nullable: false, comment: "Тип индексируемого поля")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_scheme_property", x => new { x.DiscriminatorId, x.Index });
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "setpoint",
|
name: "setpoint",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
@ -95,12 +96,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
||||||
table.PrimaryKey("PK_timestamped_values", x => new { x.DiscriminatorId, x.Timestamp });
|
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(
|
migrationBuilder.CreateTable(
|
||||||
@ -140,6 +135,9 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "parameter_data");
|
name: "parameter_data");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "scheme_property");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "setpoint");
|
name: "setpoint");
|
||||||
|
|
||||||
@ -151,9 +149,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "data_source_system");
|
name: "data_source_system");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
|
||||||
name: "data_scheme");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -64,28 +64,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
b.ToTable("change_log");
|
b.ToTable("change_log");
|
||||||
});
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataScheme", b =>
|
|
||||||
{
|
|
||||||
b.Property<Guid>("DiscriminatorId")
|
|
||||||
.ValueGeneratedOnAdd()
|
|
||||||
.HasColumnType("uuid")
|
|
||||||
.HasComment("Идентификатор схемы данных");
|
|
||||||
|
|
||||||
b.Property<string>("PropNames")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("jsonb")
|
|
||||||
.HasComment("Наименования полей в порядке индексации");
|
|
||||||
|
|
||||||
b.PrimitiveCollection<int[]>("PropTypes")
|
|
||||||
.IsRequired()
|
|
||||||
.HasColumnType("integer[]")
|
|
||||||
.HasComment("Типы полей в порядке индексации");
|
|
||||||
|
|
||||||
b.HasKey("DiscriminatorId");
|
|
||||||
|
|
||||||
b.ToTable("data_scheme");
|
|
||||||
});
|
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("SystemId")
|
b.Property<Guid>("SystemId")
|
||||||
@ -131,6 +109,30 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
b.ToTable("parameter_data");
|
b.ToTable("parameter_data");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("DD.Persistence.Database.Entity.SchemeProperty", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("DiscriminatorId")
|
||||||
|
.HasColumnType("uuid")
|
||||||
|
.HasComment("Идентификатор схемы данных");
|
||||||
|
|
||||||
|
b.Property<int>("Index")
|
||||||
|
.HasColumnType("integer")
|
||||||
|
.HasComment("Индекс поля");
|
||||||
|
|
||||||
|
b.Property<byte>("PropertyKind")
|
||||||
|
.HasColumnType("smallint")
|
||||||
|
.HasComment("Тип индексируемого поля");
|
||||||
|
|
||||||
|
b.Property<string>("PropertyName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasComment("Наименования индексируемого поля");
|
||||||
|
|
||||||
|
b.HasKey("DiscriminatorId", "Index");
|
||||||
|
|
||||||
|
b.ToTable("scheme_property");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b =>
|
modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Key")
|
b.Property<Guid>("Key")
|
||||||
@ -219,17 +221,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
|||||||
|
|
||||||
b.Navigation("System");
|
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
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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<DataScheme> GetQueryReadOnly() => db.Set<DataScheme>();
|
|
||||||
|
|
||||||
public virtual async Task Add(DataSchemeDto dataSourceSystemDto, CancellationToken token)
|
|
||||||
{
|
|
||||||
var entity = dataSourceSystemDto.Adapt<DataScheme>();
|
|
||||||
|
|
||||||
await db.Set<DataScheme>().AddAsync(entity, token);
|
|
||||||
await db.SaveChangesAsync(token);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual async Task<DataSchemeDto?> 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<DataSchemeDto>()).FirstOrDefault();
|
|
||||||
|
|
||||||
return dto;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
@ -7,12 +7,12 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Ardalis.Specification.EntityFrameworkCore" Version="8.0.0" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="UuidExtensions" Version="1.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
54
DD.Persistence.Database/DependencyInjection.cs
Normal file
54
DD.Persistence.Database/DependencyInjection.cs
Normal file
@ -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<TechMessageDto, TechMessage>()
|
||||||
|
.Ignore(dest => dest.System, dest => dest.SystemId);
|
||||||
|
|
||||||
|
TypeAdapterConfig<ChangeLog, ChangeLogDto>.NewConfig()
|
||||||
|
.Map(dest => dest.Value, src => new ChangeLogValuesDto()
|
||||||
|
{
|
||||||
|
Value = src.Value,
|
||||||
|
Id = src.Id
|
||||||
|
});
|
||||||
|
|
||||||
|
TypeAdapterConfig<KeyValuePair<Guid, SchemePropertyDto>, 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<ISetpointRepository, SetpointRepository>();
|
||||||
|
services.AddTransient<IChangeLogRepository, ChangeLogRepository>();
|
||||||
|
services.AddTransient<ITimestampedValuesRepository, TimestampedValuesRepository>();
|
||||||
|
services.AddTransient<ITechMessagesRepository, TechMessagesRepository>();
|
||||||
|
services.AddTransient<IParameterRepository, ParameterRepository>();
|
||||||
|
services.AddTransient<IDataSourceSystemRepository, DataSourceSystemCachedRepository>();
|
||||||
|
services.AddTransient<ISchemePropertyRepository, SchemePropertyCachedRepository>();
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
@ -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; } = [];
|
|
||||||
}
|
|
23
DD.Persistence.Database/Entity/SchemeProperty.cs
Normal file
23
DD.Persistence.Database/Entity/SchemeProperty.cs
Normal file
@ -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; }
|
||||||
|
}
|
@ -17,7 +17,4 @@ public class TimestampedValues : ITimestampedItem, IValuesItem
|
|||||||
|
|
||||||
[Comment("Данные"), Column(TypeName = "jsonb")]
|
[Comment("Данные"), Column(TypeName = "jsonb")]
|
||||||
public required object[] Values { get; set; }
|
public required object[] Values { get; set; }
|
||||||
|
|
||||||
[Required, ForeignKey(nameof(DiscriminatorId)), Comment("Идентификаторы")]
|
|
||||||
public virtual DataScheme? DataScheme { get; set; }
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ using System.Collections.Concurrent;
|
|||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Postgres.Extensions;
|
namespace DD.Persistence.Database.Extensions;
|
||||||
|
|
||||||
public static class EFExtensionsSortBy
|
public static class EFExtensionsSortBy
|
||||||
{
|
{
|
@ -10,7 +10,7 @@ public class PersistenceDbContext : DbContext
|
|||||||
{
|
{
|
||||||
public DbSet<Setpoint> Setpoint => Set<Setpoint>();
|
public DbSet<Setpoint> Setpoint => Set<Setpoint>();
|
||||||
|
|
||||||
public DbSet<DataScheme> DataSchemes => Set<DataScheme>();
|
public DbSet<SchemeProperty> SchemeProperty => Set<SchemeProperty>();
|
||||||
|
|
||||||
public DbSet<TimestampedValues> TimestampedValues => Set<TimestampedValues>();
|
public DbSet<TimestampedValues> TimestampedValues => Set<TimestampedValues>();
|
||||||
|
|
||||||
@ -30,10 +30,6 @@ public class PersistenceDbContext : DbContext
|
|||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
modelBuilder.Entity<DataScheme>()
|
|
||||||
.Property(e => e.PropNames)
|
|
||||||
.HasJsonConversion();
|
|
||||||
|
|
||||||
modelBuilder.Entity<TimestampedValues>()
|
modelBuilder.Entity<TimestampedValues>()
|
||||||
.Property(e => e.Values)
|
.Property(e => e.Values)
|
||||||
.HasJsonConversion();
|
.HasJsonConversion();
|
||||||
|
@ -8,7 +8,7 @@ using Mapster;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using UuidExtensions;
|
using UuidExtensions;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Postgres.Repositories;
|
namespace DD.Persistence.Database.Repositories;
|
||||||
public class ChangeLogRepository : IChangeLogRepository
|
public class ChangeLogRepository : IChangeLogRepository
|
||||||
{
|
{
|
||||||
private readonly DbContext db;
|
private readonly DbContext db;
|
||||||
@ -186,7 +186,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
|
|
||||||
var datesUpdate = await datesUpdateQuery.ToArrayAsync(token);
|
var datesUpdate = await datesUpdateQuery.ToArrayAsync(token);
|
||||||
|
|
||||||
var dates = Enumerable.Concat(datesCreate, datesUpdate);
|
var dates = datesCreate.Concat(datesUpdate);
|
||||||
var datesOnly = dates
|
var datesOnly = dates
|
||||||
.Select(d => new DateOnly(d.Year, d.Month, d.Day))
|
.Select(d => new DateOnly(d.Year, d.Month, d.Day))
|
||||||
.Distinct()
|
.Distinct()
|
||||||
@ -214,7 +214,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
public async Task<IEnumerable<ChangeLogValuesDto>> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token)
|
public async Task<IEnumerable<ChangeLogValuesDto>> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token)
|
||||||
{
|
{
|
||||||
var date = dateBegin.ToUniversalTime();
|
var date = dateBegin.ToUniversalTime();
|
||||||
var query = this.db.Set<ChangeLog>()
|
var query = db.Set<ChangeLog>()
|
||||||
.Where(e => e.IdDiscriminator == idDiscriminator)
|
.Where(e => e.IdDiscriminator == idDiscriminator)
|
||||||
.Where(e => e.Creation >= date || e.Obsolete >= date);
|
.Where(e => e.Creation >= date || e.Obsolete >= date);
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
|||||||
.Select(group => new
|
.Select(group => new
|
||||||
{
|
{
|
||||||
Min = group.Min(e => e.Creation),
|
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.Obsolete.Value
|
||||||
: e.Creation),
|
: e.Creation),
|
||||||
});
|
});
|
@ -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<SchemeProperty> GetQueryReadOnly() => db.Set<SchemeProperty>();
|
||||||
|
|
||||||
|
public virtual async Task AddRange(DataSchemeDto dataSchemeDto, CancellationToken token)
|
||||||
|
{
|
||||||
|
var entities = dataSchemeDto.Select(e =>
|
||||||
|
KeyValuePair.Create(dataSchemeDto.DiscriminatorId, e)
|
||||||
|
.Adapt<SchemeProperty>()
|
||||||
|
);
|
||||||
|
|
||||||
|
await db.Set<SchemeProperty>().AddRangeAsync(entities, token);
|
||||||
|
await db.SaveChangesAsync(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual async Task<DataSchemeDto?> 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<SchemePropertyDto>()).ToArray();
|
||||||
|
result = new DataSchemeDto(dataSchemeId, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -14,8 +14,7 @@ public class TimestampedValuesRepository : ITimestampedValuesRepository
|
|||||||
this.db = db;
|
this.db = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual IQueryable<TimestampedValues> GetQueryReadOnly() => this.db.Set<TimestampedValues>()
|
protected virtual IQueryable<TimestampedValues> GetQueryReadOnly() => this.db.Set<TimestampedValues>();
|
||||||
.Include(e => e.DataScheme);
|
|
||||||
|
|
||||||
public async virtual Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> dtos, CancellationToken token)
|
public async virtual Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> 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)));
|
.Select(g => KeyValuePair.Create(g.Key, g.OrderBy(i => i.Timestamp).Skip(skip).Take(take)));
|
||||||
var entities = await groupQuery.ToArrayAsync(token);
|
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<TimestampedValues>(root);
|
|
||||||
//var que = ApplySpecification(specification);
|
|
||||||
|
|
||||||
var result = entities.ToDictionary(k => k.Key, v => v.Value.Select(e => (
|
var result = entities.ToDictionary(k => k.Key, v => v.Value.Select(e => (
|
||||||
e.Timestamp,
|
e.Timestamp,
|
||||||
e.Values
|
e.Values
|
@ -1,21 +1,21 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Database.Postgres.Repositories;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using DD.Persistence.Database.Repositories;
|
||||||
|
|
||||||
namespace DD.Persistence.Database.Postgres.RepositoriesCached;
|
namespace DD.Persistence.Database.RepositoriesCached;
|
||||||
public class DataSchemeCachedRepository : DataSchemeRepository
|
public class SchemePropertyCachedRepository : SchemePropertyRepository
|
||||||
{
|
{
|
||||||
private readonly IMemoryCache memoryCache;
|
private readonly IMemoryCache memoryCache;
|
||||||
|
|
||||||
public DataSchemeCachedRepository(DbContext db, IMemoryCache memoryCache) : base(db)
|
public SchemePropertyCachedRepository(DbContext db, IMemoryCache memoryCache) : base(db)
|
||||||
{
|
{
|
||||||
this.memoryCache = memoryCache;
|
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);
|
memoryCache.Set(dataSourceSystemDto.DiscriminatorId, dataSourceSystemDto);
|
||||||
}
|
}
|
@ -406,8 +406,12 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest
|
|||||||
|
|
||||||
private void Cleanup()
|
private void Cleanup()
|
||||||
{
|
{
|
||||||
|
foreach (var item in discriminatorIds)
|
||||||
|
{
|
||||||
|
memoryCache.Remove(item);
|
||||||
|
}
|
||||||
discriminatorIds = [];
|
discriminatorIds = [];
|
||||||
dbContext.CleanupDbSet<TimestampedValues>();
|
dbContext.CleanupDbSet<TimestampedValues>();
|
||||||
dbContext.CleanupDbSet<DataScheme>();
|
dbContext.CleanupDbSet<SchemeProperty>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
namespace DD.Persistence.Models;
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Models;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Схема для набора данных
|
/// Схема для набора данных
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DataSchemeDto
|
public class DataSchemeDto : IEnumerable<SchemePropertyDto>, IEquatable<IEnumerable<SchemePropertyDto>>
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Дискриминатор
|
/// Дискриминатор
|
||||||
@ -11,12 +13,30 @@ public class DataSchemeDto
|
|||||||
public Guid DiscriminatorId { get; set; }
|
public Guid DiscriminatorId { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Наименования полей
|
/// Поля
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string[] PropNames { get; set; } = [];
|
private IEnumerable<SchemePropertyDto> Properties { get; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc/>
|
||||||
/// Типы полей
|
public DataSchemeDto(Guid discriminatorId, SchemePropertyDto[] Properties)
|
||||||
/// </summary>
|
{
|
||||||
public PropTypeEnum[] PropTypes { get; set; } = [];
|
DiscriminatorId = discriminatorId;
|
||||||
|
this.Properties = Properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public IEnumerator<SchemePropertyDto> GetEnumerator()
|
||||||
|
=> Properties.GetEnumerator();
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
=> GetEnumerator();
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Equals(IEnumerable<SchemePropertyDto>? otherProperties)
|
||||||
|
{
|
||||||
|
//if (otherProperties is null)
|
||||||
|
// return false;
|
||||||
|
|
||||||
|
return Properties.SequenceEqual(otherProperties);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
namespace DD.Persistence.Models;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Типы для набора данных
|
|
||||||
/// </summary>
|
|
||||||
public enum PropTypeEnum
|
|
||||||
{
|
|
||||||
/// <inheritdoc/>
|
|
||||||
String = 0,
|
|
||||||
/// <inheritdoc/>
|
|
||||||
Double = 1,
|
|
||||||
/// <inheritdoc/>
|
|
||||||
DateTime = 2
|
|
||||||
}
|
|
30
DD.Persistence.Models/SchemePropertyDto.cs
Normal file
30
DD.Persistence.Models/SchemePropertyDto.cs
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
|
namespace DD.Persistence.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Индексируемого поле из схемы для набора данных
|
||||||
|
/// </summary>
|
||||||
|
public class SchemePropertyDto : IEquatable<SchemePropertyDto>
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Индекс поля
|
||||||
|
/// </summary>
|
||||||
|
public required int Index { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Наименование индексируемого поля
|
||||||
|
/// </summary>
|
||||||
|
public required string PropertyName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Тип индексируемого поля
|
||||||
|
/// </summary>
|
||||||
|
public required JsonValueKind PropertyKind { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public bool Equals(SchemePropertyDto? other)
|
||||||
|
{
|
||||||
|
return Index == other?.Index && PropertyName == other?.PropertyName && PropertyKind == other?.PropertyKind;
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Repositories;
|
using DD.Persistence.Repositories;
|
||||||
using DD.Persistence.Services;
|
using DD.Persistence.Services;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
@ -7,8 +7,8 @@ namespace DD.Persistence.Test;
|
|||||||
public class TimestampedValuesServiceShould
|
public class TimestampedValuesServiceShould
|
||||||
{
|
{
|
||||||
private readonly ITimestampedValuesRepository timestampedValuesRepository = Substitute.For<ITimestampedValuesRepository>();
|
private readonly ITimestampedValuesRepository timestampedValuesRepository = Substitute.For<ITimestampedValuesRepository>();
|
||||||
private readonly IDataSchemeRepository dataSchemeRepository = Substitute.For<IDataSchemeRepository>();
|
private readonly ISchemePropertyRepository dataSchemeRepository = Substitute.For<ISchemePropertyRepository>();
|
||||||
private readonly TimestampedValuesService timestampedValuesService;
|
private TimestampedValuesService timestampedValuesService;
|
||||||
|
|
||||||
public TimestampedValuesServiceShould()
|
public TimestampedValuesServiceShould()
|
||||||
{
|
{
|
||||||
|
@ -5,7 +5,7 @@ namespace DD.Persistence.Repositories;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Репозиторий для работы со схемами наборов данных
|
/// Репозиторий для работы со схемами наборов данных
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IDataSchemeRepository
|
public interface ISchemePropertyRepository
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Добавить схему
|
/// Добавить схему
|
||||||
@ -13,7 +13,7 @@ public interface IDataSchemeRepository
|
|||||||
/// <param name="dataSourceSystemDto"></param>
|
/// <param name="dataSourceSystemDto"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
Task Add(DataSchemeDto dataSourceSystemDto, CancellationToken token);
|
Task AddRange(DataSchemeDto dataSourceSystemDto, CancellationToken token);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Вычитать схему
|
/// Вычитать схему
|
@ -2,6 +2,7 @@
|
|||||||
using DD.Persistence.Models;
|
using DD.Persistence.Models;
|
||||||
using DD.Persistence.Repositories;
|
using DD.Persistence.Repositories;
|
||||||
using DD.Persistence.Services.Interfaces;
|
using DD.Persistence.Services.Interfaces;
|
||||||
|
using System.Text.Json;
|
||||||
|
|
||||||
namespace DD.Persistence.Services;
|
namespace DD.Persistence.Services;
|
||||||
|
|
||||||
@ -9,10 +10,10 @@ namespace DD.Persistence.Services;
|
|||||||
public class TimestampedValuesService : ITimestampedValuesService
|
public class TimestampedValuesService : ITimestampedValuesService
|
||||||
{
|
{
|
||||||
private readonly ITimestampedValuesRepository timestampedValuesRepository;
|
private readonly ITimestampedValuesRepository timestampedValuesRepository;
|
||||||
private readonly IDataSchemeRepository dataSchemeRepository;
|
private readonly ISchemePropertyRepository dataSchemeRepository;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public TimestampedValuesService(ITimestampedValuesRepository timestampedValuesRepository, IDataSchemeRepository relatedDataRepository)
|
public TimestampedValuesService(ITimestampedValuesRepository timestampedValuesRepository, ISchemePropertyRepository relatedDataRepository)
|
||||||
{
|
{
|
||||||
this.timestampedValuesRepository = timestampedValuesRepository;
|
this.timestampedValuesRepository = timestampedValuesRepository;
|
||||||
this.dataSchemeRepository = relatedDataRepository;
|
this.dataSchemeRepository = relatedDataRepository;
|
||||||
@ -37,7 +38,7 @@ public class TimestampedValuesService : ITimestampedValuesService
|
|||||||
{
|
{
|
||||||
var result = await timestampedValuesRepository.Get(discriminatorIds, geTimestamp, columnNames, skip, take, token);
|
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())
|
if (!columnNames.IsNullOrEmpty())
|
||||||
{
|
{
|
||||||
@ -52,9 +53,9 @@ public class TimestampedValuesService : ITimestampedValuesService
|
|||||||
{
|
{
|
||||||
var result = await timestampedValuesRepository.GetFirst(discriminatorId, takeCount, token);
|
var result = await timestampedValuesRepository.GetFirst(discriminatorId, takeCount, token);
|
||||||
|
|
||||||
var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) }
|
var resultBeforeBinding = new[] { KeyValuePair.Create(discriminatorId, result) }
|
||||||
.ToDictionary();
|
.ToDictionary();
|
||||||
var dtos = await Materialize(resultToMaterialize, token);
|
var dtos = await BindingToDataScheme(resultBeforeBinding, token);
|
||||||
|
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
@ -64,9 +65,9 @@ public class TimestampedValuesService : ITimestampedValuesService
|
|||||||
{
|
{
|
||||||
var result = await timestampedValuesRepository.GetLast(discriminatorId, takeCount, token);
|
var result = await timestampedValuesRepository.GetLast(discriminatorId, takeCount, token);
|
||||||
|
|
||||||
var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) }
|
var resultBeforeBinding = new[] { KeyValuePair.Create(discriminatorId, result) }
|
||||||
.ToDictionary();
|
.ToDictionary();
|
||||||
var dtos = await Materialize(resultToMaterialize, token);
|
var dtos = await BindingToDataScheme(resultBeforeBinding, token);
|
||||||
|
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
@ -81,9 +82,9 @@ public class TimestampedValuesService : ITimestampedValuesService
|
|||||||
{
|
{
|
||||||
var result = await timestampedValuesRepository.GetResampledData(discriminatorId, beginTimestamp, intervalSec, approxPointsCount, token);
|
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();
|
.ToDictionary();
|
||||||
var dtos = await Materialize(resultToMaterialize, token);
|
var dtos = await BindingToDataScheme(resultBeforeBinding, token);
|
||||||
|
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
@ -93,41 +94,36 @@ public class TimestampedValuesService : ITimestampedValuesService
|
|||||||
{
|
{
|
||||||
var result = await timestampedValuesRepository.GetGtDate(discriminatorId, beginTimestamp, token);
|
var result = await timestampedValuesRepository.GetGtDate(discriminatorId, beginTimestamp, token);
|
||||||
|
|
||||||
var resultToMaterialize = new[] { KeyValuePair.Create(discriminatorId, result) }
|
var resultBeforeBinding = new[] { KeyValuePair.Create(discriminatorId, result) }
|
||||||
.ToDictionary();
|
.ToDictionary();
|
||||||
var dtos = await Materialize(resultToMaterialize, token);
|
var dtos = await BindingToDataScheme(resultBeforeBinding, token);
|
||||||
|
|
||||||
return dtos;
|
return dtos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToDo: рефакторинг, переименовать (текущее название не отражает суть)
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Преобразовать результат запроса в набор dto
|
/// Преобразовать результат запроса в набор dto
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="queryResult"></param>
|
/// <param name="queryResult"></param>
|
||||||
/// <param name="token"></param>
|
/// <param name="token"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
private async Task<IEnumerable<TimestampedValuesDto>> Materialize(IDictionary<Guid, IEnumerable<(DateTimeOffset Timestamp, object[] Values)>> queryResult, CancellationToken token)
|
private async Task<IEnumerable<TimestampedValuesDto>> BindingToDataScheme(IDictionary<Guid, IEnumerable<(DateTimeOffset Timestamp, object[] Values)>> queryResult, CancellationToken token)
|
||||||
{
|
{
|
||||||
IEnumerable<TimestampedValuesDto> result = [];
|
IEnumerable<TimestampedValuesDto> result = [];
|
||||||
foreach (var keyValuePair in queryResult)
|
foreach (var keyValuePair in queryResult)
|
||||||
{
|
{
|
||||||
var dataScheme = await dataSchemeRepository.Get(keyValuePair.Key, token);
|
var dataScheme = await dataSchemeRepository.Get(keyValuePair.Key, token);
|
||||||
if (dataScheme is null)
|
if (dataScheme is null)
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var tuple in keyValuePair.Value)
|
foreach (var tuple in keyValuePair.Value)
|
||||||
{
|
{
|
||||||
var identity = dataScheme!.PropNames;
|
|
||||||
var indexedIdentity = identity
|
|
||||||
.Select((value, index) => new { index, value });
|
|
||||||
|
|
||||||
var dto = new TimestampedValuesDto()
|
var dto = new TimestampedValuesDto()
|
||||||
{
|
{
|
||||||
Timestamp = tuple.Timestamp.ToUniversalTime(),
|
Timestamp = tuple.Timestamp.ToUniversalTime(),
|
||||||
Values = indexedIdentity
|
Values = dataScheme
|
||||||
.ToDictionary(x => x.value, x => tuple.Values[x.index])
|
.ToDictionary(k => k.PropertyName, v => tuple.Values[v.Index])
|
||||||
};
|
};
|
||||||
|
|
||||||
result = result.Append(dto);
|
result = result.Append(dto);
|
||||||
@ -147,60 +143,29 @@ public class TimestampedValuesService : ITimestampedValuesService
|
|||||||
/// <exception cref="InvalidOperationException">Некорректный набор наименований полей</exception>
|
/// <exception cref="InvalidOperationException">Некорректный набор наименований полей</exception>
|
||||||
private async Task CreateDataSchemeIfNotExist(Guid discriminatorId, TimestampedValuesDto dto, CancellationToken token)
|
private async Task CreateDataSchemeIfNotExist(Guid discriminatorId, TimestampedValuesDto dto, CancellationToken token)
|
||||||
{
|
{
|
||||||
var propNames = dto.Values.Keys.ToArray();
|
var valuesList = dto.Values.ToList();
|
||||||
var propTypes = GetPropTypes(dto);
|
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);
|
var dataScheme = await dataSchemeRepository.Get(discriminatorId, token);
|
||||||
if (dataScheme is null)
|
if (dataScheme is null)
|
||||||
{
|
{
|
||||||
dataScheme = new DataSchemeDto()
|
dataScheme = new DataSchemeDto(discriminatorId, properties);
|
||||||
{
|
await dataSchemeRepository.AddRange(dataScheme, token);
|
||||||
DiscriminatorId = discriminatorId,
|
|
||||||
PropNames = propNames,
|
|
||||||
PropTypes = propTypes
|
|
||||||
};
|
|
||||||
await dataSchemeRepository.Add(dataScheme, token);
|
|
||||||
|
|
||||||
return;
|
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()} " +
|
throw new InvalidOperationException($"Для системы {discriminatorId.ToString()} " +
|
||||||
$"характерен набор данных: [{expectedFieldNames}], однако был передан набор: [{actualFieldNames}]");
|
$"был передан нехарактерный набор данных");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Получить типы для набора данных в соответствии с индексацией
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="dto"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
/// <exception cref="ArgumentNullException"></exception>
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Отсеить лишние поля в соответствии с заданным фильтром
|
/// Отсеить лишние поля в соответствии с заданным фильтром
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
Loading…
Reference in New Issue
Block a user