Merge from dev
This commit is contained in:
commit
979a651328
@ -25,7 +25,6 @@
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DD.Persistence.Database.Postgres\DD.Persistence.Database.Postgres.csproj" />
|
||||
<ProjectReference Include="..\DD.Persistence.Database\DD.Persistence.Database.csproj" />
|
||||
<ProjectReference Include="..\DD.Persistence.Repository\DD.Persistence.Repository.csproj" />
|
||||
<ProjectReference Include="..\DD.Persistence\DD.Persistence.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
using DD.Persistence.Database.Model;
|
||||
using DD.Persistence.Database;
|
||||
using DD.Persistence.Database.Model;
|
||||
using DD.Persistence.Database.Postgres.Extensions;
|
||||
using DD.Persistence.Repository;
|
||||
|
||||
namespace DD.Persistence.API;
|
||||
|
||||
@ -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
|
||||
|
@ -1,6 +1,13 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DD.Persistence.Database.Entity;
|
||||
using DD.Persistence.Database.Postgres.Repositories;
|
||||
using DD.Persistence.Database.Postgres.RepositoriesCached;
|
||||
using DD.Persistence.Models;
|
||||
using DD.Persistence.Repositories;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace DD.Persistence.Database.Model;
|
||||
|
||||
|
@ -13,7 +13,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
namespace DD.Persistence.Database.Postgres.Migrations
|
||||
{
|
||||
[DbContext(typeof(PersistencePostgresContext))]
|
||||
[Migration("20250203061429_Init")]
|
||||
[Migration("20250205114037_Init")]
|
||||
partial class Init
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@ -67,23 +67,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
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.HasKey("DiscriminatorId");
|
||||
|
||||
b.ToTable("data_scheme");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
||||
{
|
||||
b.Property<Guid>("SystemId")
|
||||
@ -129,6 +112,30 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
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 =>
|
||||
{
|
||||
b.Property<Guid>("Key")
|
||||
@ -217,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
|
||||
}
|
||||
}
|
@ -30,18 +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<Guid>(type: "uuid", nullable: false, comment: "Идентификатор схемы данных"),
|
||||
PropNames = table.Column<string>(type: "jsonb", nullable: false, comment: "Наименования полей в порядке индексации")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_data_scheme", x => x.DiscriminatorId);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "data_source_system",
|
||||
columns: table => new
|
||||
@ -69,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<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(
|
||||
name: "setpoint",
|
||||
columns: table => new
|
||||
@ -94,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(
|
||||
@ -139,6 +135,9 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "parameter_data");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "scheme_property");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "setpoint");
|
||||
|
||||
@ -150,9 +149,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "data_source_system");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "data_scheme");
|
||||
}
|
||||
}
|
||||
}
|
@ -64,23 +64,6 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
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.HasKey("DiscriminatorId");
|
||||
|
||||
b.ToTable("data_scheme");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
||||
{
|
||||
b.Property<Guid>("SystemId")
|
||||
@ -126,6 +109,30 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
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 =>
|
||||
{
|
||||
b.Property<Guid>("Key")
|
||||
@ -214,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
|
||||
}
|
||||
}
|
||||
|
@ -7,11 +7,13 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="UuidExtensions" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,15 +1,19 @@
|
||||
using DD.Persistence.Database.Entity;
|
||||
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 DD.Persistence.Repository.Repositories;
|
||||
using DD.Persistence.Repository.RepositoriesCached;
|
||||
using Mapster;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace DD.Persistence.Repository;
|
||||
namespace DD.Persistence.Database;
|
||||
|
||||
public static class DependencyInjection
|
||||
{
|
||||
// ToDo: перенести в другой файл
|
||||
public static void MapsterSetup()
|
||||
{
|
||||
TypeAdapterConfig.GlobalSettings.Default.Config
|
||||
@ -22,6 +26,12 @@ public static class DependencyInjection
|
||||
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)
|
||||
@ -38,7 +48,7 @@ public static class DependencyInjection
|
||||
services.AddTransient<ITechMessagesRepository, TechMessagesRepository>();
|
||||
services.AddTransient<IParameterRepository, ParameterRepository>();
|
||||
services.AddTransient<IDataSourceSystemRepository, DataSourceSystemCachedRepository>();
|
||||
services.AddTransient<IDataSchemeRepository, DataSchemeCachedRepository>();
|
||||
services.AddTransient<ISchemePropertyRepository, SchemePropertyCachedRepository>();
|
||||
|
||||
return services;
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
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; } = [];
|
||||
}
|
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
|
||||
|
||||
[Comment("Данные"), Column(TypeName = "jsonb")]
|
||||
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.Reflection;
|
||||
|
||||
namespace DD.Persistence.Repository.Extensions;
|
||||
namespace DD.Persistence.Database.Extensions;
|
||||
|
||||
public static class EFExtensionsSortBy
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
using System.Collections;
|
||||
|
||||
namespace DD.Persistence.Repository;
|
||||
namespace DD.Persistence.Database.Postgres.Helpers;
|
||||
/// <summary>
|
||||
/// Цикличный массив
|
||||
/// </summary>
|
@ -1,11 +1,10 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using DD.Persistence.Models.Requests;
|
||||
using DD.Persistence.Models.Common;
|
||||
using DD.Persistence.ModelsAbstractions;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
using DD.Persistence.Extensions;
|
||||
using DD.Persistence.Models.Common;
|
||||
using DD.Persistence.Models.Requests;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DD.Persistence.Repository;
|
||||
namespace DD.Persistence.Database.Postgres.Helpers;
|
||||
|
||||
/// <summary>
|
||||
/// класс с набором методов, необходимых для фильтрации записей
|
@ -10,7 +10,7 @@ public class PersistenceDbContext : DbContext
|
||||
{
|
||||
public DbSet<Setpoint> Setpoint => Set<Setpoint>();
|
||||
|
||||
public DbSet<DataScheme> DataSchemes => Set<DataScheme>();
|
||||
public DbSet<SchemeProperty> SchemeProperty => Set<SchemeProperty>();
|
||||
|
||||
public DbSet<TimestampedValues> TimestampedValues => Set<TimestampedValues>();
|
||||
|
||||
@ -30,10 +30,6 @@ public class PersistenceDbContext : DbContext
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder.Entity<DataScheme>()
|
||||
.Property(e => e.PropNames)
|
||||
.HasJsonConversion();
|
||||
|
||||
modelBuilder.Entity<TimestampedValues>()
|
||||
.Property(e => e.Values)
|
||||
.HasJsonConversion();
|
||||
|
@ -1,4 +1,5 @@
|
||||
using DD.Persistence.Database.Entity;
|
||||
using DD.Persistence.Database.Postgres.Helpers;
|
||||
using DD.Persistence.Models;
|
||||
using DD.Persistence.Models.Common;
|
||||
using DD.Persistence.Models.Requests;
|
||||
@ -7,7 +8,7 @@ using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using UuidExtensions;
|
||||
|
||||
namespace DD.Persistence.Repository.Repositories;
|
||||
namespace DD.Persistence.Database.Repositories;
|
||||
public class ChangeLogRepository : IChangeLogRepository
|
||||
{
|
||||
private readonly DbContext db;
|
||||
@ -185,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()
|
||||
@ -213,7 +214,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
public async Task<IEnumerable<ChangeLogValuesDto>> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token)
|
||||
{
|
||||
var date = dateBegin.ToUniversalTime();
|
||||
var query = this.db.Set<ChangeLog>()
|
||||
var query = db.Set<ChangeLog>()
|
||||
.Where(e => e.IdDiscriminator == idDiscriminator)
|
||||
.Where(e => e.Creation >= date || e.Obsolete >= date);
|
||||
|
||||
@ -232,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),
|
||||
});
|
@ -4,7 +4,7 @@ using DD.Persistence.Repositories;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DD.Persistence.Repository.Repositories;
|
||||
namespace DD.Persistence.Database.Postgres.Repositories;
|
||||
public class DataSourceSystemRepository : IDataSourceSystemRepository
|
||||
{
|
||||
protected DbContext db;
|
@ -5,7 +5,7 @@ using DD.Persistence.Models;
|
||||
using DD.Persistence.Repositories;
|
||||
using DD.Persistence.Models.Common;
|
||||
|
||||
namespace DD.Persistence.Repository.Repositories;
|
||||
namespace DD.Persistence.Database.Postgres.Repositories;
|
||||
public class ParameterRepository : IParameterRepository
|
||||
{
|
||||
private DbContext db;
|
@ -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;
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace DD.Persistence.Repository.Repositories
|
||||
namespace DD.Persistence.Database.Postgres.Repositories
|
||||
{
|
||||
public class SetpointRepository : ISetpointRepository
|
||||
{
|
@ -7,7 +7,7 @@ using DD.Persistence.Repositories;
|
||||
using Mapster;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DD.Persistence.Repository.Repositories
|
||||
namespace DD.Persistence.Database.Postgres.Repositories
|
||||
{
|
||||
public class TechMessagesRepository : ITechMessagesRepository
|
||||
{
|
@ -4,7 +4,7 @@ using DD.Persistence.Models.Common;
|
||||
using DD.Persistence.Repositories;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace DD.Persistence.Repository.Repositories;
|
||||
namespace DD.Persistence.Database.Postgres.Repositories;
|
||||
public class TimestampedValuesRepository : ITimestampedValuesRepository
|
||||
{
|
||||
private readonly DbContext db;
|
@ -1,10 +1,10 @@
|
||||
using DD.Persistence.Database.Entity;
|
||||
using DD.Persistence.Models;
|
||||
using DD.Persistence.Repository.Repositories;
|
||||
using DD.Persistence.Database.Postgres.Repositories;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace DD.Persistence.Repository.RepositoriesCached;
|
||||
namespace DD.Persistence.Database.Postgres.RepositoriesCached;
|
||||
public class DataSourceSystemCachedRepository : DataSourceSystemRepository
|
||||
{
|
||||
private static readonly string SystemCacheKey = $"{typeof(DataSourceSystem).FullName}CacheKey";
|
@ -1,21 +1,21 @@
|
||||
using DD.Persistence.Models;
|
||||
using DD.Persistence.Repository.Repositories;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using DD.Persistence.Database.Repositories;
|
||||
|
||||
namespace DD.Persistence.Repository.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);
|
||||
}
|
@ -3,7 +3,6 @@ using DD.Persistence.Client.Clients;
|
||||
using DD.Persistence.Client.Clients.Interfaces;
|
||||
using DD.Persistence.Client.Clients.Interfaces.Refit;
|
||||
using DD.Persistence.Database.Entity;
|
||||
using DD.Persistence.Extensions;
|
||||
using DD.Persistence.Models;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@ -407,8 +406,12 @@ public class TimestampedValuesControllerTest : BaseIntegrationTest
|
||||
|
||||
private void Cleanup()
|
||||
{
|
||||
foreach (var item in discriminatorIds)
|
||||
{
|
||||
memoryCache.Remove(item);
|
||||
}
|
||||
discriminatorIds = [];
|
||||
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>
|
||||
public class DataSchemeDto
|
||||
public class DataSchemeDto : IEnumerable<SchemePropertyDto>, IEquatable<IEnumerable<SchemePropertyDto>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Дискриминатор
|
||||
@ -11,7 +13,30 @@ public class DataSchemeDto
|
||||
public Guid DiscriminatorId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Наименования полей
|
||||
/// Поля
|
||||
/// </summary>
|
||||
public string[] PropNames { get; set; } = [];
|
||||
private IEnumerable<SchemePropertyDto> Properties { get; } = [];
|
||||
|
||||
/// <inheritdoc/>
|
||||
public DataSchemeDto(Guid discriminatorId, IEnumerable<SchemePropertyDto> Properties)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
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;
|
||||
}
|
||||
}
|
@ -20,7 +20,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DD.Persistence.Database.Postgres\DD.Persistence.Database.Postgres.csproj" />
|
||||
<ProjectReference Include="..\DD.Persistence.Repository\DD.Persistence.Repository.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
@ -1,12 +1,7 @@
|
||||
using DD.Persistence.Database.Model;
|
||||
using DD.Persistence.Repository.Repositories;
|
||||
using DD.Persistence.Database.Postgres.Repositories;
|
||||
using Shouldly;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DD.Persistence.Repository.Test;
|
||||
public class SetpointRepositoryShould : IClassFixture<RepositoryTestFixture>
|
||||
|
@ -1,19 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Mapster" Version="7.4.0" />
|
||||
<PackageReference Include="UuidExtensions" Version="1.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DD.Persistence.Database\DD.Persistence.Database.csproj" />
|
||||
<ProjectReference Include="..\DD.Persistence\DD.Persistence.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -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.Repository.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,103 +0,0 @@
|
||||
//using DD.Persistence.Models;
|
||||
//using DD.Persistence.Models.Common;
|
||||
//using DD.Persistence.Repositories;
|
||||
//using Microsoft.EntityFrameworkCore;
|
||||
|
||||
//namespace DD.Persistence.Repository.Repositories;
|
||||
|
||||
//public class TimestampedValuesCachedRepository : TimestampedValuesRepository
|
||||
//{
|
||||
// public static TimestampedValuesDto? FirstByDate { get; private set; }
|
||||
// public static CyclicArray<TimestampedValuesDto> LastData { get; } = new CyclicArray<TimestampedValuesDto>(CacheItemsCount);
|
||||
|
||||
// private const int CacheItemsCount = 3600;
|
||||
|
||||
// public TimestampedValuesCachedRepository(DbContext db, IDataSourceSystemRepository<ValuesIdentityDto> relatedDataRepository) : base(db, relatedDataRepository)
|
||||
// {
|
||||
// //Task.Run(async () =>
|
||||
// //{
|
||||
// // var firstDateItem = await base.GetFirst(CancellationToken.None);
|
||||
// // if (firstDateItem == null)
|
||||
// // {
|
||||
// // return;
|
||||
// // }
|
||||
|
||||
// // FirstByDate = firstDateItem;
|
||||
|
||||
// // var dtos = await base.GetLast(CacheItemsCount, CancellationToken.None);
|
||||
// // dtos = dtos.OrderBy(d => d.Timestamp);
|
||||
// // LastData.AddRange(dtos);
|
||||
// //}).Wait();
|
||||
// }
|
||||
|
||||
// public override async Task<IEnumerable<TimestampedValuesDto>> GetGtDate(Guid discriminatorId, DateTimeOffset dateBegin, CancellationToken token)
|
||||
// {
|
||||
|
||||
// if (LastData.Count == 0 || LastData[0].Timestamp > dateBegin)
|
||||
// {
|
||||
// var dtos = await base.GetGtDate(discriminatorId, dateBegin, token);
|
||||
// return dtos;
|
||||
// }
|
||||
|
||||
// var items = LastData
|
||||
// .Where(i => i.Timestamp >= dateBegin);
|
||||
|
||||
// return items;
|
||||
// }
|
||||
|
||||
// public override async Task<int> AddRange(Guid discriminatorId, IEnumerable<TimestampedValuesDto> dtos, CancellationToken token)
|
||||
// {
|
||||
// var result = await base.AddRange(discriminatorId, dtos, token);
|
||||
// if (result > 0)
|
||||
// {
|
||||
|
||||
// dtos = dtos.OrderBy(x => x.Timestamp);
|
||||
|
||||
// FirstByDate = dtos.First();
|
||||
// LastData.AddRange(dtos);
|
||||
// }
|
||||
|
||||
// return result;
|
||||
// }
|
||||
|
||||
// public override async Task<DatesRangeDto?> GetDatesRange(Guid discriminatorId, CancellationToken token)
|
||||
// {
|
||||
// if (FirstByDate == null)
|
||||
// return null;
|
||||
|
||||
// return await Task.Run(() =>
|
||||
// {
|
||||
// return new DatesRangeDto
|
||||
// {
|
||||
// From = FirstByDate.Timestamp,
|
||||
// To = LastData[^1].Timestamp
|
||||
// };
|
||||
// });
|
||||
// }
|
||||
|
||||
// public override async Task<IEnumerable<TimestampedValuesDto>> GetResampledData(
|
||||
// Guid discriminatorId,
|
||||
// DateTimeOffset dateBegin,
|
||||
// double intervalSec = 600d,
|
||||
// int approxPointsCount = 1024,
|
||||
// CancellationToken token = default)
|
||||
// {
|
||||
// var dtos = LastData.Where(i => i.Timestamp >= dateBegin);
|
||||
// if (LastData.Count == 0 || LastData[0].Timestamp > dateBegin)
|
||||
// {
|
||||
// dtos = await base.GetGtDate(discriminatorId, dateBegin, token);
|
||||
// }
|
||||
|
||||
// var dateEnd = dateBegin.AddSeconds(intervalSec);
|
||||
// dtos = dtos
|
||||
// .Where(i => i.Timestamp <= dateEnd);
|
||||
|
||||
// var ratio = dtos.Count() / approxPointsCount;
|
||||
// if (ratio > 1)
|
||||
// dtos = dtos
|
||||
// .Where((_, index) => index % ratio == 0);
|
||||
|
||||
// return dtos;
|
||||
// }
|
||||
//}
|
||||
|
@ -2,12 +2,13 @@
|
||||
using DD.Persistence.Repositories;
|
||||
using DD.Persistence.Services;
|
||||
using NSubstitute;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace DD.Persistence.Repository.Test;
|
||||
public class TimestampedValuesServiceShould
|
||||
{
|
||||
private readonly ITimestampedValuesRepository timestampedValuesRepository = Substitute.For<ITimestampedValuesRepository>();
|
||||
private readonly IDataSchemeRepository dataSchemeRepository = Substitute.For<IDataSchemeRepository>();
|
||||
private readonly ISchemePropertyRepository dataSchemeRepository = Substitute.For<ISchemePropertyRepository>();
|
||||
private TimestampedValuesService timestampedValuesService;
|
||||
|
||||
public TimestampedValuesServiceShould()
|
||||
@ -45,10 +46,10 @@ public class TimestampedValuesServiceShould
|
||||
{
|
||||
var values = new Dictionary<string, object>()
|
||||
{
|
||||
{ "A", i },
|
||||
{ "B", i * 1.1 },
|
||||
{ "C", $"Any{i}" },
|
||||
{ "D", DateTimeOffset.Now },
|
||||
{ "A", GetJsonFromObject(i) },
|
||||
{ "B", GetJsonFromObject(i * 1.1) },
|
||||
{ "C", GetJsonFromObject($"Any{i}") },
|
||||
{ "D", GetJsonFromObject(DateTimeOffset.Now) }
|
||||
};
|
||||
|
||||
yield return new TimestampedValuesDto()
|
||||
@ -58,4 +59,11 @@ public class TimestampedValuesServiceShould
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private static JsonElement GetJsonFromObject(object value)
|
||||
{
|
||||
var jsonString = JsonSerializer.Serialize(value);
|
||||
var doc = JsonDocument.Parse(jsonString);
|
||||
return doc.RootElement;
|
||||
}
|
||||
}
|
||||
|
@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DD.Persistence", "DD.Persis
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DD.Persistence.API", "DD.Persistence.API\DD.Persistence.API.csproj", "{8650A227-929E-45F0-AEF7-2C91F45FE884}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DD.Persistence.Repository", "DD.Persistence.Repository\DD.Persistence.Repository.csproj", "{493D6D92-231B-4CB6-831B-BE13884B0DE4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DD.Persistence.Database", "DD.Persistence.Database\DD.Persistence.Database.csproj", "{F77475D1-D074-407A-9D69-2FADDDAE2056}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DD.Persistence.IntegrationTests", "DD.Persistence.IntegrationTests\DD.Persistence.IntegrationTests.csproj", "{10752C25-3773-4081-A1F2-215A1D950126}"
|
||||
@ -51,10 +49,6 @@ Global
|
||||
{8650A227-929E-45F0-AEF7-2C91F45FE884}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8650A227-929E-45F0-AEF7-2C91F45FE884}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8650A227-929E-45F0-AEF7-2C91F45FE884}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{493D6D92-231B-4CB6-831B-BE13884B0DE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{493D6D92-231B-4CB6-831B-BE13884B0DE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{493D6D92-231B-4CB6-831B-BE13884B0DE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{493D6D92-231B-4CB6-831B-BE13884B0DE4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{F77475D1-D074-407A-9D69-2FADDDAE2056}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{F77475D1-D074-407A-9D69-2FADDDAE2056}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{F77475D1-D074-407A-9D69-2FADDDAE2056}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
@ -5,7 +5,7 @@ namespace DD.Persistence.Repositories;
|
||||
/// <summary>
|
||||
/// Репозиторий для работы со схемами наборов данных
|
||||
/// </summary>
|
||||
public interface IDataSchemeRepository
|
||||
public interface ISchemePropertyRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// Добавить схему
|
||||
@ -13,7 +13,7 @@ public interface IDataSchemeRepository
|
||||
/// <param name="dataSourceSystemDto"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
Task Add(DataSchemeDto dataSourceSystemDto, CancellationToken token);
|
||||
Task AddRange(DataSchemeDto dataSourceSystemDto, CancellationToken token);
|
||||
|
||||
/// <summary>
|
||||
/// Вычитать схему
|
@ -1,8 +1,8 @@
|
||||
using DD.Persistence.Extensions;
|
||||
using DD.Persistence.Models;
|
||||
using DD.Persistence.Models.Common;
|
||||
using DD.Persistence.Repositories;
|
||||
using DD.Persistence.Services.Interfaces;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace DD.Persistence.Services;
|
||||
|
||||
@ -10,10 +10,10 @@ namespace DD.Persistence.Services;
|
||||
public class TimestampedValuesService : ITimestampedValuesService
|
||||
{
|
||||
private readonly ITimestampedValuesRepository timestampedValuesRepository;
|
||||
private readonly IDataSchemeRepository dataSchemeRepository;
|
||||
private readonly ISchemePropertyRepository dataSchemeRepository;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public TimestampedValuesService(ITimestampedValuesRepository timestampedValuesRepository, IDataSchemeRepository relatedDataRepository)
|
||||
public TimestampedValuesService(ITimestampedValuesRepository timestampedValuesRepository, ISchemePropertyRepository relatedDataRepository)
|
||||
{
|
||||
this.timestampedValuesRepository = timestampedValuesRepository;
|
||||
this.dataSchemeRepository = relatedDataRepository;
|
||||
@ -25,8 +25,7 @@ public class TimestampedValuesService : ITimestampedValuesService
|
||||
// ToDo: реализовать без foreach
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var keys = dto.Values.Keys.ToArray();
|
||||
await CreateSystemSpecificationIfNotExist(discriminatorId, keys, token);
|
||||
await CreateDataSchemeIfNotExist(discriminatorId, dto, token);
|
||||
}
|
||||
|
||||
var result = await timestampedValuesRepository.AddRange(discriminatorId, dtos, token);
|
||||
@ -39,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())
|
||||
{
|
||||
@ -54,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;
|
||||
}
|
||||
@ -66,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;
|
||||
}
|
||||
@ -83,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;
|
||||
}
|
||||
@ -95,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: рефакторинг, переименовать (текущее название не отражает суть)
|
||||
/// <summary>
|
||||
/// Преобразовать результат запроса в набор dto
|
||||
/// </summary>
|
||||
/// <param name="queryResult"></param>
|
||||
/// <param name="token"></param>
|
||||
/// <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 = [];
|
||||
foreach (var keyValuePair in queryResult)
|
||||
{
|
||||
var dataScheme = await dataSchemeRepository.Get(keyValuePair.Key, token);
|
||||
if (dataScheme is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var tuple in keyValuePair.Value)
|
||||
foreach (var (Timestamp, Values) 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])
|
||||
Timestamp = Timestamp.ToUniversalTime(),
|
||||
Values = dataScheme
|
||||
.ToDictionary(k => k.PropertyName, v => Values[v.Index])
|
||||
};
|
||||
|
||||
result = result.Append(dto);
|
||||
@ -140,34 +134,36 @@ public class TimestampedValuesService : ITimestampedValuesService
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Создать спецификацию, при отсутствии таковой
|
||||
/// Создать схему данных, при отсутствии таковой
|
||||
/// </summary>
|
||||
/// <param name="discriminatorId">Дискриминатор системы</param>
|
||||
/// <param name="fieldNames">Набор наименований полей</param>
|
||||
/// <param name="discriminatorId">Дискриминатор схемы</param>
|
||||
/// <param name="dto">Набор данных, по образу которого будет создана соответствующая схема</param>
|
||||
/// <param name="token"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="InvalidOperationException">Некорректный набор наименований полей</exception>
|
||||
private async Task CreateSystemSpecificationIfNotExist(Guid discriminatorId, string[] fieldNames, CancellationToken token)
|
||||
private async Task CreateDataSchemeIfNotExist(Guid discriminatorId, TimestampedValuesDto dto, CancellationToken token)
|
||||
{
|
||||
var systemSpecification = await dataSchemeRepository.Get(discriminatorId, token);
|
||||
if (systemSpecification is null)
|
||||
var valuesList = dto.Values.ToList();
|
||||
var properties = valuesList.Select((e, index) => new SchemePropertyDto()
|
||||
{
|
||||
systemSpecification = new DataSchemeDto()
|
||||
Index = index,
|
||||
PropertyName = e.Key,
|
||||
PropertyKind = ((JsonElement)e.Value).ValueKind
|
||||
});
|
||||
|
||||
var dataScheme = await dataSchemeRepository.Get(discriminatorId, token);
|
||||
if (dataScheme is null)
|
||||
{
|
||||
DiscriminatorId = discriminatorId,
|
||||
PropNames = fieldNames
|
||||
};
|
||||
await dataSchemeRepository.Add(systemSpecification, token);
|
||||
dataScheme = new DataSchemeDto(discriminatorId, properties);
|
||||
await dataSchemeRepository.AddRange(dataScheme, token);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!systemSpecification.PropNames.SequenceEqual(fieldNames))
|
||||
if (!dataScheme.Equals(properties))
|
||||
{
|
||||
var expectedFieldNames = string.Join(", ", systemSpecification.PropNames);
|
||||
var actualFieldNames = string.Join(", ", fieldNames);
|
||||
throw new InvalidOperationException($"Для системы {discriminatorId.ToString()} " +
|
||||
$"характерен набор данных: [{expectedFieldNames}], однако был передан набор: [{actualFieldNames}]");
|
||||
$"был передан нехарактерный набор данных");
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,7 +173,7 @@ public class TimestampedValuesService : ITimestampedValuesService
|
||||
/// <param name="dtos"></param>
|
||||
/// <param name="fieldNames">Поля, которые необходимо оставить</param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<TimestampedValuesDto> ReduceSetColumnsByNames(IEnumerable<TimestampedValuesDto> dtos, IEnumerable<string> fieldNames)
|
||||
private static IEnumerable<TimestampedValuesDto> ReduceSetColumnsByNames(IEnumerable<TimestampedValuesDto> dtos, IEnumerable<string> fieldNames)
|
||||
{
|
||||
var result = dtos.Select(dto =>
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user