diff --git a/Persistence.API/Controllers/TechMessagesController.cs b/Persistence.API/Controllers/TechMessagesController.cs
index 7411c19..fb3315e 100644
--- a/Persistence.API/Controllers/TechMessagesController.cs
+++ b/Persistence.API/Controllers/TechMessagesController.cs
@@ -11,7 +11,7 @@ namespace Persistence.API.Controllers;
[ApiController]
[Authorize]
[Route("api/[controller]")]
-public class TechMessagesController : ControllerBase, ITechMessages
+public class TechMessagesController : ControllerBase
{
private readonly ITechMessagesRepository techMessagesRepository;
@@ -41,8 +41,8 @@ public class TechMessagesController : ControllerBase, ITechMessages
///
///
///
- [HttpGet("statistics")]
- public async Task> GetStatistics(int importantId, string autoDrillingSystem, CancellationToken token)
+ [HttpGet("statistics/{autoDrillingSystem}")]
+ public async Task> GetStatistics([FromRoute] string? autoDrillingSystem, int? importantId, CancellationToken token)
{
var result = await techMessagesRepository.GetStatistics(importantId, autoDrillingSystem, token);
diff --git a/Persistence.API/DependencyInjection.cs b/Persistence.API/DependencyInjection.cs
index 5d7c646..19cedc9 100644
--- a/Persistence.API/DependencyInjection.cs
+++ b/Persistence.API/DependencyInjection.cs
@@ -1,9 +1,12 @@
using System.Reflection;
using System.Text.Json.Nodes;
+using Mapster;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
+using Persistence.Database.Entity;
+using Persistence.Models;
using Persistence.Models.Configurations;
using Swashbuckle.AspNetCore.SwaggerGen;
@@ -11,6 +14,12 @@ namespace Persistence.API;
public static class DependencyInjection
{
+ public static void MapsterSetup()
+ {
+ TypeAdapterConfig.GlobalSettings.Default.Config
+ .ForType()
+ .Ignore(dest => dest.System, dest => dest.SystemId);
+ }
public static void AddSwagger(this IServiceCollection services, IConfiguration configuration)
{
services.AddSwaggerGen(c =>
diff --git a/Persistence.API/Startup.cs b/Persistence.API/Startup.cs
index e074845..98ad4aa 100644
--- a/Persistence.API/Startup.cs
+++ b/Persistence.API/Startup.cs
@@ -23,6 +23,9 @@ public class Startup
services.AddInfrastructure();
services.AddPersistenceDbContext(Configuration);
services.AddJWTAuthentication(Configuration);
+ services.AddMemoryCache();
+
+ DependencyInjection.MapsterSetup();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
diff --git a/Persistence.Database.Postgres/Migrations/20241126044756_TechMessageMigration.cs b/Persistence.Database.Postgres/Migrations/20241126044756_TechMessageMigration.cs
deleted file mode 100644
index 46a71a0..0000000
--- a/Persistence.Database.Postgres/Migrations/20241126044756_TechMessageMigration.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-using System;
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace Persistence.Database.Postgres.Migrations
-{
- ///
- public partial class TechMessageMigration : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.AlterColumn(
- name: "Created",
- table: "Setpoint",
- type: "timestamp with time zone",
- nullable: false,
- comment: "Дата создания уставки",
- oldClrType: typeof(DateTimeOffset),
- oldType: "timestamp with time zone",
- oldComment: "Дата изменения уставки");
-
- migrationBuilder.CreateTable(
- name: "TechMessage",
- columns: table => new
- {
- EventId = table.Column(type: "uuid", nullable: false, comment: "Id события"),
- ImportantId = table.Column(type: "integer", nullable: false, comment: "Id Категории важности"),
- OccurrenceDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "Дата возникновения"),
- Depth = table.Column(type: "double precision", nullable: true, comment: "Глубина забоя"),
- MessageText = table.Column(type: "varchar(512)", nullable: true, comment: "Текст сообщения"),
- AutoDrillingSystem = table.Column(type: "varchar(256)", nullable: true, comment: "Система автобурения, к которой относится сообщение"),
- UserId = table.Column(type: "uuid", nullable: false, comment: "Id пользователя за пультом бурильщика")
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_TechMessage", x => x.EventId);
- });
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "TechMessage");
-
- migrationBuilder.AlterColumn(
- name: "Created",
- table: "Setpoint",
- type: "timestamp with time zone",
- nullable: false,
- comment: "Дата изменения уставки",
- oldClrType: typeof(DateTimeOffset),
- oldType: "timestamp with time zone",
- oldComment: "Дата создания уставки");
- }
- }
-}
diff --git a/Persistence.Database.Postgres/Migrations/20241126044756_TechMessageMigration.Designer.cs b/Persistence.Database.Postgres/Migrations/20241127123045_TechMessageMigration.Designer.cs
similarity index 71%
rename from Persistence.Database.Postgres/Migrations/20241126044756_TechMessageMigration.Designer.cs
rename to Persistence.Database.Postgres/Migrations/20241127123045_TechMessageMigration.Designer.cs
index 5d6817e..2e5a30a 100644
--- a/Persistence.Database.Postgres/Migrations/20241126044756_TechMessageMigration.Designer.cs
+++ b/Persistence.Database.Postgres/Migrations/20241127123045_TechMessageMigration.Designer.cs
@@ -12,7 +12,7 @@ using Persistence.Database.Model;
namespace Persistence.Database.Postgres.Migrations
{
[DbContext(typeof(PersistenceDbContext))]
- [Migration("20241126044756_TechMessageMigration")]
+ [Migration("20241127123045_TechMessageMigration")]
partial class TechMessageMigration
{
///
@@ -27,6 +27,27 @@ namespace Persistence.Database.Postgres.Migrations
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+ modelBuilder.Entity("Persistence.Database.Entity.ADSystem", b =>
+ {
+ b.Property("SystemId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid")
+ .HasComment("Id системы автобурения");
+
+ b.Property("Description")
+ .HasColumnType("text")
+ .HasComment("Описание системы автобурения");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("varchar(256)")
+ .HasComment("Наименование системы автобурения");
+
+ b.HasKey("SystemId");
+
+ b.ToTable("ADSystem");
+ });
+
modelBuilder.Entity("Persistence.Database.Entity.TechMessage", b =>
{
b.Property("EventId")
@@ -34,10 +55,6 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("uuid")
.HasComment("Id события");
- b.Property("AutoDrillingSystem")
- .HasColumnType("varchar(256)")
- .HasComment("Система автобурения, к которой относится сообщение");
-
b.Property("Depth")
.HasColumnType("double precision")
.HasComment("Глубина забоя");
@@ -47,6 +64,7 @@ namespace Persistence.Database.Postgres.Migrations
.HasComment("Id Категории важности");
b.Property("MessageText")
+ .IsRequired()
.HasColumnType("varchar(512)")
.HasComment("Текст сообщения");
@@ -54,15 +72,44 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("timestamp with time zone")
.HasComment("Дата возникновения");
+ b.Property("SystemId")
+ .HasColumnType("uuid")
+ .HasComment("Id системы автобурения, к которой относится сообщение");
+
b.Property("UserId")
.HasColumnType("uuid")
.HasComment("Id пользователя за пультом бурильщика");
b.HasKey("EventId");
+ b.HasIndex("SystemId");
+
b.ToTable("TechMessage");
});
+ modelBuilder.Entity("Persistence.Database.Entity.TimestampedSet", b =>
+ {
+ b.Property("IdDiscriminator")
+ .HasColumnType("uuid")
+ .HasComment("Дискриминатор ссылка на тип сохраняемых данных");
+
+ b.Property("Timestamp")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("Отметка времени, строго в UTC");
+
+ b.Property("Set")
+ .IsRequired()
+ .HasColumnType("jsonb")
+ .HasComment("Набор сохраняемых данных");
+
+ b.HasKey("IdDiscriminator", "Timestamp");
+
+ b.ToTable("TimestampedSets", t =>
+ {
+ t.HasComment("Общая таблица данных временных рядов");
+ });
+ });
+
modelBuilder.Entity("Persistence.Database.Model.DataSaub", b =>
{
b.Property("Date")
@@ -169,6 +216,17 @@ namespace Persistence.Database.Postgres.Migrations
b.ToTable("Setpoint");
});
+
+ modelBuilder.Entity("Persistence.Database.Entity.TechMessage", b =>
+ {
+ b.HasOne("Persistence.Database.Entity.ADSystem", "System")
+ .WithMany()
+ .HasForeignKey("SystemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("System");
+ });
#pragma warning restore 612, 618
}
}
diff --git a/Persistence.Database.Postgres/Migrations/20241127123045_TechMessageMigration.cs b/Persistence.Database.Postgres/Migrations/20241127123045_TechMessageMigration.cs
new file mode 100644
index 0000000..d3a5ac2
--- /dev/null
+++ b/Persistence.Database.Postgres/Migrations/20241127123045_TechMessageMigration.cs
@@ -0,0 +1,83 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace Persistence.Database.Postgres.Migrations
+{
+ ///
+ public partial class TechMessageMigration : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "ADSystem",
+ columns: table => new
+ {
+ SystemId = table.Column(type: "uuid", nullable: false, comment: "Id системы автобурения"),
+ Name = table.Column(type: "varchar(256)", nullable: false, comment: "Наименование системы автобурения"),
+ Description = table.Column(type: "text", nullable: true, comment: "Описание системы автобурения")
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_ADSystem", x => x.SystemId);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "TimestampedSets",
+ columns: table => new
+ {
+ IdDiscriminator = table.Column(type: "uuid", nullable: false, comment: "Дискриминатор ссылка на тип сохраняемых данных"),
+ Timestamp = table.Column(type: "timestamp with time zone", nullable: false, comment: "Отметка времени, строго в UTC"),
+ Set = table.Column(type: "jsonb", nullable: false, comment: "Набор сохраняемых данных")
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_TimestampedSets", x => new { x.IdDiscriminator, x.Timestamp });
+ },
+ comment: "Общая таблица данных временных рядов");
+
+ migrationBuilder.CreateTable(
+ name: "TechMessage",
+ columns: table => new
+ {
+ EventId = table.Column(type: "uuid", nullable: false, comment: "Id события"),
+ ImportantId = table.Column(type: "integer", nullable: false, comment: "Id Категории важности"),
+ OccurrenceDate = table.Column(type: "timestamp with time zone", nullable: false, comment: "Дата возникновения"),
+ Depth = table.Column(type: "double precision", nullable: true, comment: "Глубина забоя"),
+ MessageText = table.Column(type: "varchar(512)", nullable: false, comment: "Текст сообщения"),
+ SystemId = table.Column(type: "uuid", nullable: false, comment: "Id системы автобурения, к которой относится сообщение"),
+ UserId = table.Column(type: "uuid", nullable: false, comment: "Id пользователя за пультом бурильщика")
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_TechMessage", x => x.EventId);
+ table.ForeignKey(
+ name: "FK_TechMessage_ADSystem_SystemId",
+ column: x => x.SystemId,
+ principalTable: "ADSystem",
+ principalColumn: "SystemId",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_TechMessage_SystemId",
+ table: "TechMessage",
+ column: "SystemId");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "TechMessage");
+
+ migrationBuilder.DropTable(
+ name: "TimestampedSets");
+
+ migrationBuilder.DropTable(
+ name: "ADSystem");
+ }
+ }
+}
diff --git a/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs b/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs
index 4446a1c..317c445 100644
--- a/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs
+++ b/Persistence.Database.Postgres/Migrations/PersistenceDbContextModelSnapshot.cs
@@ -24,6 +24,27 @@ namespace Persistence.Database.Postgres.Migrations
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "adminpack");
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+ modelBuilder.Entity("Persistence.Database.Entity.ADSystem", b =>
+ {
+ b.Property("SystemId")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid")
+ .HasComment("Id системы автобурения");
+
+ b.Property("Description")
+ .HasColumnType("text")
+ .HasComment("Описание системы автобурения");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("varchar(256)")
+ .HasComment("Наименование системы автобурения");
+
+ b.HasKey("SystemId");
+
+ b.ToTable("ADSystem");
+ });
+
modelBuilder.Entity("Persistence.Database.Entity.TechMessage", b =>
{
b.Property("EventId")
@@ -31,10 +52,6 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("uuid")
.HasComment("Id события");
- b.Property("AutoDrillingSystem")
- .HasColumnType("varchar(256)")
- .HasComment("Система автобурения, к которой относится сообщение");
-
b.Property("Depth")
.HasColumnType("double precision")
.HasComment("Глубина забоя");
@@ -44,6 +61,7 @@ namespace Persistence.Database.Postgres.Migrations
.HasComment("Id Категории важности");
b.Property("MessageText")
+ .IsRequired()
.HasColumnType("varchar(512)")
.HasComment("Текст сообщения");
@@ -51,15 +69,44 @@ namespace Persistence.Database.Postgres.Migrations
.HasColumnType("timestamp with time zone")
.HasComment("Дата возникновения");
+ b.Property("SystemId")
+ .HasColumnType("uuid")
+ .HasComment("Id системы автобурения, к которой относится сообщение");
+
b.Property("UserId")
.HasColumnType("uuid")
.HasComment("Id пользователя за пультом бурильщика");
b.HasKey("EventId");
+ b.HasIndex("SystemId");
+
b.ToTable("TechMessage");
});
+ modelBuilder.Entity("Persistence.Database.Entity.TimestampedSet", b =>
+ {
+ b.Property("IdDiscriminator")
+ .HasColumnType("uuid")
+ .HasComment("Дискриминатор ссылка на тип сохраняемых данных");
+
+ b.Property("Timestamp")
+ .HasColumnType("timestamp with time zone")
+ .HasComment("Отметка времени, строго в UTC");
+
+ b.Property("Set")
+ .IsRequired()
+ .HasColumnType("jsonb")
+ .HasComment("Набор сохраняемых данных");
+
+ b.HasKey("IdDiscriminator", "Timestamp");
+
+ b.ToTable("TimestampedSets", t =>
+ {
+ t.HasComment("Общая таблица данных временных рядов");
+ });
+ });
+
modelBuilder.Entity("Persistence.Database.Model.DataSaub", b =>
{
b.Property("Date")
@@ -166,6 +213,17 @@ namespace Persistence.Database.Postgres.Migrations
b.ToTable("Setpoint");
});
+
+ modelBuilder.Entity("Persistence.Database.Entity.TechMessage", b =>
+ {
+ b.HasOne("Persistence.Database.Entity.ADSystem", "System")
+ .WithMany()
+ .HasForeignKey("SystemId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("System");
+ });
#pragma warning restore 612, 618
}
}
diff --git a/Persistence.Database/Entity/ADSystem.cs b/Persistence.Database/Entity/ADSystem.cs
new file mode 100644
index 0000000..525134c
--- /dev/null
+++ b/Persistence.Database/Entity/ADSystem.cs
@@ -0,0 +1,16 @@
+using System.ComponentModel.DataAnnotations;
+using System.ComponentModel.DataAnnotations.Schema;
+using Microsoft.EntityFrameworkCore;
+
+namespace Persistence.Database.Entity;
+public class ADSystem
+{
+ [Key, Comment("Id системы автобурения")]
+ public Guid SystemId { get; set; }
+
+ [Required, Column(TypeName = "varchar(256)"), Comment("Наименование системы автобурения")]
+ public required string Name { get; set; }
+
+ [Comment("Описание системы автобурения")]
+ public string? Description { get; set; }
+}
diff --git a/Persistence.Database/Entity/TechMessage.cs b/Persistence.Database/Entity/TechMessage.cs
index b4135c1..dce897c 100644
--- a/Persistence.Database/Entity/TechMessage.cs
+++ b/Persistence.Database/Entity/TechMessage.cs
@@ -19,10 +19,13 @@ namespace Persistence.Database.Entity
public double? Depth { get; set; }
[Column(TypeName = "varchar(512)"), Comment("Текст сообщения")]
- public string? MessageText { get; set; }
+ public required string MessageText { get; set; }
- [Column(TypeName = "varchar(256)"), Comment("Система автобурения, к которой относится сообщение")]
- public string? AutoDrillingSystem { get; set; }
+ [Required, Comment("Id системы автобурения, к которой относится сообщение")]
+ public required Guid SystemId { get; set; }
+
+ [Required, ForeignKey(nameof(SystemId)), Comment("Система автобурения, к которой относится сообщение")]
+ public virtual required ADSystem System { get; set; }
[Comment("Id пользователя за пультом бурильщика")]
public Guid UserId { get; set; }
diff --git a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs
index 9eb0e9d..73414c4 100644
--- a/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs
+++ b/Persistence.IntegrationTests/Controllers/TechMessagesControllerTest.cs
@@ -29,7 +29,7 @@ namespace Persistence.IntegrationTests.Controllers
{
Skip = 1,
Take = 2,
- SortSettings = nameof(TechMessageDto.ImportantId)
+ SortSettings = nameof(TechMessageDto.CategoryId)
};
//act
@@ -53,7 +53,7 @@ namespace Persistence.IntegrationTests.Controllers
{
Skip = 0,
Take = 2,
- SortSettings = nameof(TechMessageDto.ImportantId)
+ SortSettings = nameof(TechMessageDto.CategoryId)
};
//act
@@ -90,7 +90,7 @@ namespace Persistence.IntegrationTests.Controllers
//arrange
var dtos = await InsertRange();
var systems = dtos
- .Select(e => e.AutoDrillingSystem)
+ .Select(e => e.System)
.Distinct()
.ToArray();
@@ -110,7 +110,7 @@ namespace Persistence.IntegrationTests.Controllers
//arrange
dbContext.CleanupDbSet();
var imortantId = 1;
- var autoDrillingSystem = nameof(TechMessageDto.AutoDrillingSystem);
+ var autoDrillingSystem = nameof(TechMessageDto.System);
//act
var response = await techMessagesClient.GetStatistics(imortantId, autoDrillingSystem, new CancellationToken());
@@ -125,9 +125,9 @@ namespace Persistence.IntegrationTests.Controllers
{
//arrange
var imortantId = 1;
- var autoDrillingSystem = nameof(TechMessageDto.AutoDrillingSystem);
+ var autoDrillingSystem = nameof(TechMessageDto.System);
var dtos = await InsertRange();
- var filteredDtos = dtos.Where(e => e.ImportantId == imortantId && e.AutoDrillingSystem == e.AutoDrillingSystem);
+ var filteredDtos = dtos.Where(e => e.CategoryId == imortantId && e.System == e.System);
//act
var response = await techMessagesClient.GetStatistics(imortantId, autoDrillingSystem, new CancellationToken());
@@ -145,21 +145,21 @@ namespace Persistence.IntegrationTests.Controllers
new TechMessageDto()
{
EventId = Guid.NewGuid(),
- ImportantId = 1,
- OccurrenceDate = DateTimeOffset.UtcNow,
+ CategoryId = 1,
+ Timestamp = DateTimeOffset.UtcNow,
Depth = 1.11,
MessageText = nameof(TechMessageDto.MessageText),
- AutoDrillingSystem = nameof(TechMessageDto.AutoDrillingSystem),
+ System = nameof(TechMessageDto.System),
UserId = Guid.NewGuid()
},
new TechMessageDto()
{
EventId = Guid.NewGuid(),
- ImportantId = 2,
- OccurrenceDate = DateTimeOffset.UtcNow,
+ CategoryId = 2,
+ Timestamp = DateTimeOffset.UtcNow,
Depth = 2.22,
MessageText = nameof(TechMessageDto.MessageText),
- AutoDrillingSystem = nameof(TechMessageDto.AutoDrillingSystem),
+ System = nameof(TechMessageDto.System),
UserId = Guid.NewGuid()
}
};
diff --git a/Persistence.Repository/Repositories/TechMessagesRepository.cs b/Persistence.Repository/Repositories/TechMessagesRepository.cs
index 9abda86..427346b 100644
--- a/Persistence.Repository/Repositories/TechMessagesRepository.cs
+++ b/Persistence.Repository/Repositories/TechMessagesRepository.cs
@@ -1,5 +1,7 @@
using Mapster;
using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.Caching.Memory;
+using Newtonsoft.Json.Linq;
using Persistence.Database.Entity;
using Persistence.Models;
using Persistence.Repositories;
@@ -9,9 +11,13 @@ namespace Persistence.Repository.Repositories
{
public class TechMessagesRepository : ITechMessagesRepository
{
+ private static readonly string SystemCacheKey = $"{typeof(ADSystem).FullName}CacheKey";
+ private readonly IMemoryCache memoryCache;
private DbContext db;
- public TechMessagesRepository(DbContext db)
+
+ public TechMessagesRepository(DbContext db, IMemoryCache memoryCache)
{
+ this.memoryCache = memoryCache;
this.db = db;
}
@@ -36,36 +42,75 @@ namespace Persistence.Repository.Repositories
return dto;
}
- public async Task GetStatistics(int importantId, string autoDrillingSystem, CancellationToken token)
+ public async Task> GetStatistics(int? importantId, string? autoDrillingSystem, CancellationToken token)
{
var query = GetQueryReadOnly();
var count = await query
- .Where(e => e.ImportantId == importantId && e.AutoDrillingSystem == autoDrillingSystem)
- .CountAsync();
+ .Where(e => importantId == null || e.ImportantId == importantId)
+ .Where(e => autoDrillingSystem == null || e.System.Name == autoDrillingSystem)
+ .GroupBy(e => e.System.Name)
+ .ToDictionaryAsync(e => e.Key, v => v.Count());
return count;
}
- public async Task> GetSystems(CancellationToken token)
+ public async Task> GetSystems(CancellationToken token)
{
- var query = GetQueryReadOnly();
- var entities = await query
- .Select(e => e.AutoDrillingSystem ?? string.Empty)
- .Distinct()
- .ToArrayAsync(token);
- var dtos = entities.Order();
+ var systems = await memoryCache.GetOrCreateAsync(SystemCacheKey, async f =>
+ {
+ f.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(60);
- return dtos;
+ var query = db.Set();
+ var entities = await query.ToListAsync();
+ var dtos = entities.Select(e => e.Adapt());
+
+ return dtos;
+ });
+
+ return systems ?? [];
}
public async Task InsertRange(IEnumerable dtos, CancellationToken token)
{
- var entities = dtos.Select(d => d.Adapt());
+ var entities = dtos.Select(dto =>
+ {
+ var task = Task.Run(async () =>
+ {
+ var entity = dto.Adapt();
+ var systems = await GetSystems(token);
+ var systemId = systems.FirstOrDefault(e => e.Name == dto.System)?.SystemId
+ ?? await CreateSystem(dto.System);
+
+ entity.SystemId = systemId;
+
+ return entity;
+ });
+ task.Wait();
+
+ return task.Result;
+ });
await db.Set().AddRangeAsync(entities, token);
var result = await db.SaveChangesAsync(token);
return result;
}
+
+ private async Task CreateSystem(string name)
+ {
+ memoryCache.Remove(SystemCacheKey);
+
+ var systemId = Guid.NewGuid();
+ var entity = new ADSystem()
+ {
+ SystemId = systemId,
+ Name = name
+ };
+
+ await db.Set().AddAsync(entity);
+ await db.SaveChangesAsync();
+
+ return Guid.NewGuid();
+ }
}
}
diff --git a/Persistence/API/ITechMessages.cs b/Persistence/API/ITechMessages.cs
deleted file mode 100644
index 95af161..0000000
--- a/Persistence/API/ITechMessages.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Persistence.Models;
-
-namespace Persistence.API
-{
- ///
- /// Интерфейс для API сообщений о состояниях работы систем автобурения (АБ)
- ///
- public interface ITechMessages : ITableDataApi
- {
- ///
- /// Добавление новых сообщений
- ///
- ///
- ///
- ///
- Task> InsertRange(IEnumerable dtos, CancellationToken token);
-
- ///
- /// Получение списка систем АБ
- ///
- ///
- ///
- Task>> GetSystems(CancellationToken token);
-
- ///
- /// Получение статистики
- ///
- /// Id Категории важности
- /// Система АБ
- ///
- ///
- Task> GetStatistics(int importantId, string autoDrillingSystem, CancellationToken token);
- }
-}
diff --git a/Persistence/Models/ADSystemDto.cs b/Persistence/Models/ADSystemDto.cs
new file mode 100644
index 0000000..d11dfc7
--- /dev/null
+++ b/Persistence/Models/ADSystemDto.cs
@@ -0,0 +1,22 @@
+namespace Persistence.Models;
+
+///
+/// Модель системы автобурения
+///
+public class ADSystemDto
+{
+ ///
+ /// Ключ
+ ///
+ public Guid SystemId { get; set; }
+
+ ///
+ /// Наименование
+ ///
+ public required string Name { get; set; }
+
+ ///
+ /// Описание
+ ///
+ public string? Description { get; set; }
+}
diff --git a/Persistence/Models/TechMessageDto.cs b/Persistence/Models/TechMessageDto.cs
index 625b22f..84da656 100644
--- a/Persistence/Models/TechMessageDto.cs
+++ b/Persistence/Models/TechMessageDto.cs
@@ -1,4 +1,6 @@
-namespace Persistence.Models
+using System.ComponentModel.DataAnnotations;
+
+namespace Persistence.Models
{
///
/// Модель технологического сообщения
@@ -8,32 +10,39 @@
///
/// Id события
///
+ [Required]
public Guid EventId { get; set; }
///
/// Id Категории важности
///
- public int ImportantId { get; set; }
+ [Range(0, int.MaxValue, ErrorMessage = "Id Категории важности не может быть меньше 0")]
+ public int CategoryId { get; set; }
///
/// Дата возникновения
///
- public DateTimeOffset OccurrenceDate { get; set; }
+ public DateTimeOffset Timestamp { get; set; }
///
/// Глубина забоя
///
+ [Range(0, double.MaxValue, ErrorMessage = "Глубина забоя не может быть меньше 0")]
public double? Depth { get; set; }
///
/// Текст сообщения
///
- public string? MessageText { get; set; }
+ [Required]
+ [StringLength(512, MinimumLength = 1, ErrorMessage = "Допустимая длина текста сообщения от 1 до 512 символов")]
+ public required string MessageText { get; set; }
///
/// Система автобурения, к которой относится сообщение
///
- public string? AutoDrillingSystem { get; set; }
+ [Required]
+ [StringLength(256, MinimumLength = 1, ErrorMessage = "Допустимая длина наименования системы АБ от 1 до 256 символов")]
+ public required string System { get; set; }
///
/// Id пользователя за пультом бурильщика
diff --git a/Persistence/Repositories/ITechMessagesRepository.cs b/Persistence/Repositories/ITechMessagesRepository.cs
index 1be90e9..b8fb194 100644
--- a/Persistence/Repositories/ITechMessagesRepository.cs
+++ b/Persistence/Repositories/ITechMessagesRepository.cs
@@ -1,4 +1,5 @@
-using Persistence.Models;
+using System.Threading.Tasks;
+using Persistence.Models;
namespace Persistence.Repositories
{
@@ -28,7 +29,7 @@ namespace Persistence.Repositories
///
///
///
- Task> GetSystems(CancellationToken token);
+ Task> GetSystems(CancellationToken token);
///
/// Получение количества сообщений по категориям и системам автобурения
@@ -37,6 +38,6 @@ namespace Persistence.Repositories
/// Система автобурения
///
///
- Task GetStatistics(int importantId, string autoDrillingSystem, CancellationToken token);
+ Task> GetStatistics(int? importantId, string? autoDrillingSystem, CancellationToken token);
}
}