Compare commits
1 Commits
master
...
feature/sp
Author | SHA1 | Date | |
---|---|---|---|
2c66adfae7 |
@ -9,7 +9,7 @@ using DD.Persistence.Models.Common;
|
||||
namespace DD.Persistence.API.Controllers;
|
||||
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
//[Authorize]
|
||||
[Route("api/[controller]")]
|
||||
public class ChangeLogController : ControllerBase, IChangeLogApi
|
||||
{
|
||||
|
@ -12,7 +12,7 @@ namespace DD.Persistence.API.Controllers;
|
||||
/// Работа с уставками
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Authorize]
|
||||
//[Authorize]
|
||||
[Route("api/[controller]")]
|
||||
public class SetpointController : ControllerBase, ISetpointApi
|
||||
{
|
||||
@ -105,8 +105,8 @@ public class SetpointController : ControllerBase, ISetpointApi
|
||||
[ProducesResponseType(typeof(int), (int)HttpStatusCode.Created)]
|
||||
public async Task<IActionResult> Add(Guid setpointKey, object newValue, CancellationToken token)
|
||||
{
|
||||
var userId = User.GetUserId<Guid>();
|
||||
await setpointRepository.Add(setpointKey, (JsonElement)newValue, userId, token);
|
||||
//var userId = User.GetUserId<Guid>();
|
||||
await setpointRepository.Add(setpointKey, (JsonElement)newValue, Guid.NewGuid(), token);
|
||||
|
||||
return CreatedAtAction(nameof(Add), true);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"DbConnection": {
|
||||
"Host": "postgres",
|
||||
"Host": "localhost",
|
||||
"Port": 5432,
|
||||
"Database": "persistence",
|
||||
"Username": "postgres",
|
||||
"Password": "postgres"
|
||||
"Password": "q"
|
||||
},
|
||||
"NeedUseKeyCloak": false,
|
||||
"AuthUser": {
|
||||
|
@ -6,7 +6,7 @@
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=localhost;Database=persistence;Username=postgres;Password=postgres;Persist Security Info=True"
|
||||
"DefaultConnection": "Host=localhost:5462;Database=persistence;Username=postgres;Password=postgres;Persist Security Info=True"
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"NeedUseKeyCloak": false,
|
||||
|
@ -0,0 +1,230 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using System.Text.Json;
|
||||
using DD.Persistence.Database.Model;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace DD.Persistence.Database.Postgres.Migrations
|
||||
{
|
||||
[DbContext(typeof(PersistencePostgresContext))]
|
||||
[Migration("20250210104036_IdDiscriminatorUpdateToDiscriminatorId")]
|
||||
partial class IdDiscriminatorUpdateToDiscriminatorId
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.ChangeLog", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Ключ записи");
|
||||
|
||||
b.Property<DateTimeOffset>("Creation")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("Дата создания записи");
|
||||
|
||||
b.Property<Guid>("DiscriminatorId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Дискриминатор таблицы");
|
||||
|
||||
b.Property<Guid>("IdAuthor")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Автор изменения");
|
||||
|
||||
b.Property<Guid?>("IdEditor")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Редактор");
|
||||
|
||||
b.Property<Guid?>("IdNext")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Id заменяющей записи");
|
||||
|
||||
b.Property<DateTimeOffset?>("Obsolete")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("Дата устаревания (например при удалении)");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasComment("Значение");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("change_log");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.DataSourceSystem", b =>
|
||||
{
|
||||
b.Property<Guid>("SystemId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Id системы - источника данных");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text")
|
||||
.HasComment("Описание системы - источника данных");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(256)")
|
||||
.HasComment("Наименование системы - источника данных");
|
||||
|
||||
b.HasKey("SystemId");
|
||||
|
||||
b.ToTable("data_source_system");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.ParameterData", b =>
|
||||
{
|
||||
b.Property<Guid>("DiscriminatorId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Дискриминатор системы");
|
||||
|
||||
b.Property<int>("ParameterId")
|
||||
.HasColumnType("integer")
|
||||
.HasComment("Id параметра");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("Временная отметка");
|
||||
|
||||
b.Property<string>("Value")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(256)")
|
||||
.HasComment("Значение параметра в виде строки");
|
||||
|
||||
b.HasKey("DiscriminatorId", "ParameterId", "Timestamp");
|
||||
|
||||
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>("DiscriminatorId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Ключ");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("Дата создания уставки");
|
||||
|
||||
b.Property<Guid>("IdUser")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Id автора последнего изменения");
|
||||
|
||||
b.Property<JsonElement>("Value")
|
||||
.HasColumnType("jsonb")
|
||||
.HasComment("Значение уставки");
|
||||
|
||||
b.HasKey("DiscriminatorId", "Timestamp");
|
||||
|
||||
b.ToTable("setpoint");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
||||
{
|
||||
b.Property<Guid>("EventId")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Id события");
|
||||
|
||||
b.Property<int>("CategoryId")
|
||||
.HasColumnType("integer")
|
||||
.HasComment("Id Категории важности");
|
||||
|
||||
b.Property<int>("EventState")
|
||||
.HasColumnType("integer")
|
||||
.HasComment("Статус события");
|
||||
|
||||
b.Property<Guid>("SystemId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Id системы, к которой относится сообщение");
|
||||
|
||||
b.Property<string>("Text")
|
||||
.IsRequired()
|
||||
.HasColumnType("varchar(512)")
|
||||
.HasComment("Текст сообщения");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("Дата возникновения");
|
||||
|
||||
b.HasKey("EventId");
|
||||
|
||||
b.HasIndex("SystemId");
|
||||
|
||||
b.ToTable("tech_message");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TimestampedValues", b =>
|
||||
{
|
||||
b.Property<Guid>("DiscriminatorId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Дискриминатор системы");
|
||||
|
||||
b.Property<DateTimeOffset>("Timestamp")
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("Временная отметка");
|
||||
|
||||
b.Property<string>("Values")
|
||||
.IsRequired()
|
||||
.HasColumnType("jsonb")
|
||||
.HasComment("Данные");
|
||||
|
||||
b.HasKey("DiscriminatorId", "Timestamp");
|
||||
|
||||
b.ToTable("timestamped_values");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.TechMessage", b =>
|
||||
{
|
||||
b.HasOne("DD.Persistence.Database.Entity.DataSourceSystem", "System")
|
||||
.WithMany()
|
||||
.HasForeignKey("SystemId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("System");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace DD.Persistence.Database.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class IdDiscriminatorUpdateToDiscriminatorId : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "Key",
|
||||
table: "setpoint",
|
||||
newName: "DiscriminatorId");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "IdDiscriminator",
|
||||
table: "change_log",
|
||||
newName: "DiscriminatorId");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "DiscriminatorId",
|
||||
table: "setpoint",
|
||||
newName: "Key");
|
||||
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "DiscriminatorId",
|
||||
table: "change_log",
|
||||
newName: "IdDiscriminator");
|
||||
}
|
||||
}
|
||||
}
|
@ -34,14 +34,14 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
.HasColumnType("timestamp with time zone")
|
||||
.HasComment("Дата создания записи");
|
||||
|
||||
b.Property<Guid>("DiscriminatorId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Дискриминатор таблицы");
|
||||
|
||||
b.Property<Guid>("IdAuthor")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Автор изменения");
|
||||
|
||||
b.Property<Guid>("IdDiscriminator")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Дискриминатор таблицы");
|
||||
|
||||
b.Property<Guid?>("IdEditor")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Редактор");
|
||||
@ -135,7 +135,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
|
||||
modelBuilder.Entity("DD.Persistence.Database.Entity.Setpoint", b =>
|
||||
{
|
||||
b.Property<Guid>("Key")
|
||||
b.Property<Guid>("DiscriminatorId")
|
||||
.HasColumnType("uuid")
|
||||
.HasComment("Ключ");
|
||||
|
||||
@ -151,7 +151,7 @@ namespace DD.Persistence.Database.Postgres.Migrations
|
||||
.HasColumnType("jsonb")
|
||||
.HasComment("Значение уставки");
|
||||
|
||||
b.HasKey("Key", "Timestamp");
|
||||
b.HasKey("DiscriminatorId", "Timestamp");
|
||||
|
||||
b.ToTable("setpoint");
|
||||
});
|
||||
|
@ -11,13 +11,13 @@ namespace DD.Persistence.Database.Entity;
|
||||
/// Часть записи, описывающая изменение
|
||||
/// </summary>
|
||||
[Table("change_log")]
|
||||
public class ChangeLog : IChangeLog
|
||||
public class ChangeLog : IChangeLog, IDiscriminatorItem
|
||||
{
|
||||
[Key, Comment("Ключ записи")]
|
||||
public Guid Id { get; set; }
|
||||
|
||||
[Comment("Дискриминатор таблицы")]
|
||||
public Guid IdDiscriminator { get; set; }
|
||||
public Guid DiscriminatorId { get; set; }
|
||||
|
||||
[Comment("Автор изменения")]
|
||||
public Guid IdAuthor { get; set; }
|
||||
|
@ -6,11 +6,11 @@ using System.Text.Json;
|
||||
namespace DD.Persistence.Database.Entity;
|
||||
|
||||
[Table("setpoint")]
|
||||
[PrimaryKey(nameof(Key), nameof(Timestamp))]
|
||||
public class Setpoint : ITimestampedItem
|
||||
[PrimaryKey(nameof(DiscriminatorId), nameof(Timestamp))]
|
||||
public class Setpoint : ITimestampedItem, IDiscriminatorItem
|
||||
{
|
||||
[Comment("Ключ")]
|
||||
public Guid Key { get; set; }
|
||||
public Guid DiscriminatorId { get; set; }
|
||||
|
||||
[Column(TypeName = "jsonb"), Comment("Значение уставки")]
|
||||
public required JsonElement Value { get; set; }
|
||||
|
@ -38,7 +38,7 @@ public interface IChangeLog
|
||||
/// <summary>
|
||||
/// Дискриминатор таблицы
|
||||
/// </summary>
|
||||
public Guid IdDiscriminator { get; set; }
|
||||
public Guid DiscriminatorId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Значение
|
||||
|
@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DD.Persistence.Database.EntityAbstractions;
|
||||
public interface IDiscriminatorItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Дискриминатор
|
||||
/// </summary>
|
||||
Guid DiscriminatorId { get; set; }
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
using DD.Persistence.Database.Entity;
|
||||
using Ardalis.Specification;
|
||||
using Ardalis.Specification.EntityFrameworkCore;
|
||||
using DD.Persistence.Database.Entity;
|
||||
using DD.Persistence.Database.Postgres.Helpers;
|
||||
using DD.Persistence.Database.Specifications.ChangeLog;
|
||||
using DD.Persistence.Database.Specifications.Common.DiscriminatorItem;
|
||||
using DD.Persistence.Models;
|
||||
using DD.Persistence.Models.Common;
|
||||
using DD.Persistence.Models.Requests;
|
||||
@ -12,10 +16,13 @@ namespace DD.Persistence.Database.Repositories;
|
||||
public class ChangeLogRepository : IChangeLogRepository
|
||||
{
|
||||
private readonly DbContext db;
|
||||
private readonly ObsoleteIsNullSpec<ChangeLog> obsoleteIsNullSpecification;
|
||||
|
||||
public ChangeLogRepository(DbContext db)
|
||||
{
|
||||
this.db = db;
|
||||
|
||||
this.obsoleteIsNullSpecification = new ObsoleteIsNullSpec<ChangeLog>();
|
||||
}
|
||||
|
||||
public async Task<int> AddRange(Guid idAuthor, Guid idDiscriminator, IEnumerable<ChangeLogValuesDto> dtos, CancellationToken token)
|
||||
@ -35,9 +42,11 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
|
||||
public async Task<int> MarkAsDeleted(Guid idEditor, IEnumerable<Guid> ids, CancellationToken token)
|
||||
{
|
||||
var containsIdsSpecification = new IdContainsSpec<ChangeLog>(ids);
|
||||
|
||||
var query = db.Set<ChangeLog>()
|
||||
.Where(s => ids.Contains(s.Id))
|
||||
.Where(s => s.Obsolete == null);
|
||||
.WithSpecification(containsIdsSpecification)
|
||||
.WithSpecification(obsoleteIsNullSpecification);
|
||||
|
||||
if (query.Count() != ids.Count())
|
||||
{
|
||||
@ -53,9 +62,11 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
|
||||
public async Task<int> MarkAsDeleted(Guid idEditor, Guid idDiscriminator, CancellationToken token)
|
||||
{
|
||||
var specDiscriminatorEqual = new DiscriminatorEqualSpec<ChangeLog>(idDiscriminator);
|
||||
|
||||
var query = db.Set<ChangeLog>()
|
||||
.Where(s => s.IdDiscriminator == idDiscriminator)
|
||||
.Where(e => e.Obsolete == null);
|
||||
.WithSpecification(specDiscriminatorEqual)
|
||||
.WithSpecification(obsoleteIsNullSpecification);
|
||||
|
||||
var entities = await query.ToArrayAsync(token);
|
||||
|
||||
@ -97,8 +108,10 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
var dbSet = db.Set<ChangeLog>();
|
||||
|
||||
var updatedIds = dtos.Select(d => d.Id);
|
||||
var containsIdsSpecification = new IdContainsSpec<ChangeLog>(updatedIds);
|
||||
|
||||
var updatedEntities = dbSet
|
||||
.Where(s => updatedIds.Contains(s.Id))
|
||||
.WithSpecification(containsIdsSpecification)
|
||||
.ToDictionary(s => s.Id);
|
||||
|
||||
var result = 0;
|
||||
@ -112,7 +125,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
throw new ArgumentException($"Entity with id = {dto.Id} doesn't exist in Db", nameof(dto));
|
||||
}
|
||||
|
||||
var newEntity = CreateEntityFromDto(idEditor, updatedEntity.IdDiscriminator, dto);
|
||||
var newEntity = CreateEntityFromDto(idEditor, updatedEntity.DiscriminatorId, dto);
|
||||
dbSet.Add(newEntity);
|
||||
|
||||
updatedEntity.IdNext = newEntity.Id;
|
||||
@ -134,7 +147,11 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
PaginationRequest paginationRequest,
|
||||
CancellationToken token)
|
||||
{
|
||||
var query = CreateQuery(idDiscriminator);
|
||||
var specDiscriminatorEqual = new DiscriminatorEqualSpec<ChangeLog>(idDiscriminator);
|
||||
|
||||
var query = db.Set<ChangeLog>()
|
||||
.WithSpecification(specDiscriminatorEqual);
|
||||
|
||||
query = query.Apply(momentUtc);
|
||||
|
||||
var result = await query.ApplyPagination(paginationRequest, Convert, token);
|
||||
@ -142,22 +159,21 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
return result;
|
||||
}
|
||||
|
||||
private IQueryable<ChangeLog> CreateQuery(Guid idDiscriminator)
|
||||
{
|
||||
var query = db.Set<ChangeLog>().Where(e => e.IdDiscriminator == idDiscriminator);
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ChangeLogDto>> GetChangeLogForInterval(Guid idDiscriminator, DateTimeOffset dateBegin, DateTimeOffset dateEnd, CancellationToken token)
|
||||
{
|
||||
var query = db.Set<ChangeLog>().Where(s => s.IdDiscriminator == idDiscriminator);
|
||||
var specDiscriminatorEqual = new DiscriminatorEqualSpec<ChangeLog>(idDiscriminator);
|
||||
|
||||
var query = db.Set<ChangeLog>()
|
||||
.WithSpecification(specDiscriminatorEqual);
|
||||
|
||||
var min = new DateTimeOffset(dateBegin.ToUniversalTime().Date, TimeSpan.Zero);
|
||||
var max = new DateTimeOffset(dateEnd.ToUniversalTime().Date, TimeSpan.Zero);
|
||||
|
||||
var createdQuery = query.Where(e => e.Creation >= min && e.Creation <= max);
|
||||
var editedQuery = query.Where(e => e.Obsolete != null && e.Obsolete >= min && e.Obsolete <= max);
|
||||
var specCreatedByDateRange = new FromCreationDateRangeSpec<ChangeLog>(min, max);
|
||||
var specHistoryByDateRange = new FromObsoleteDateRangeSpece<ChangeLog>(min, max);
|
||||
|
||||
var createdQuery = query.WithSpecification(specCreatedByDateRange);
|
||||
var editedQuery = query.WithSpecification(specHistoryByDateRange);
|
||||
|
||||
query = createdQuery.Union(editedQuery);
|
||||
var entities = await query.ToArrayAsync(token);
|
||||
@ -171,7 +187,11 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
|
||||
public async Task<IEnumerable<DateOnly>> GetDatesChange(Guid idDiscriminator, CancellationToken token)
|
||||
{
|
||||
var query = db.Set<ChangeLog>().Where(e => e.IdDiscriminator == idDiscriminator);
|
||||
var specDiscriminatorEqual = new DiscriminatorEqualSpec<ChangeLog>(idDiscriminator);
|
||||
var specObsoleteNotNull = new ObsoleteNotNullSpec<ChangeLog>();
|
||||
|
||||
var query = db.Set<ChangeLog>()
|
||||
.WithSpecification(specDiscriminatorEqual);
|
||||
|
||||
var datesCreateQuery = query
|
||||
.Select(e => e.Creation)
|
||||
@ -180,7 +200,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
var datesCreate = await datesCreateQuery.ToArrayAsync(token);
|
||||
|
||||
var datesUpdateQuery = query
|
||||
.Where(e => e.Obsolete != null)
|
||||
.WithSpecification(specObsoleteNotNull)
|
||||
.Select(e => e.Obsolete!.Value)
|
||||
.Distinct();
|
||||
|
||||
@ -202,7 +222,7 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
Id = Uuid7.Guid(),
|
||||
Creation = DateTimeOffset.UtcNow,
|
||||
IdAuthor = idAuthor,
|
||||
IdDiscriminator = idDiscriminator,
|
||||
DiscriminatorId = idDiscriminator,
|
||||
IdEditor = idAuthor,
|
||||
|
||||
Value = dto.Value
|
||||
@ -214,9 +234,13 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
public async Task<IEnumerable<ChangeLogValuesDto>> GetGtDate(Guid idDiscriminator, DateTimeOffset dateBegin, CancellationToken token)
|
||||
{
|
||||
var date = dateBegin.ToUniversalTime();
|
||||
|
||||
var specDiscriminatorEqual = new DiscriminatorEqualSpec<ChangeLog>(idDiscriminator);
|
||||
var specCreatedOrUpdatedGeDate = new CreatedOrUpdatedGeDateSpec<ChangeLog>(date);
|
||||
|
||||
var query = db.Set<ChangeLog>()
|
||||
.Where(e => e.IdDiscriminator == idDiscriminator)
|
||||
.Where(e => e.Creation >= date || e.Obsolete >= date);
|
||||
.WithSpecification(specDiscriminatorEqual)
|
||||
.WithSpecification(specCreatedOrUpdatedGeDate);
|
||||
|
||||
var entities = await query.ToArrayAsync(token);
|
||||
|
||||
@ -227,29 +251,34 @@ public class ChangeLogRepository : IChangeLogRepository
|
||||
|
||||
public async Task<DatesRangeDto?> GetDatesRange(Guid idDiscriminator, CancellationToken token)
|
||||
{
|
||||
var query = db.Set<ChangeLog>()
|
||||
.Where(e => e.IdDiscriminator == idDiscriminator)
|
||||
.GroupBy(e => 1)
|
||||
.Select(group => new
|
||||
{
|
||||
Min = group.Min(e => e.Creation),
|
||||
Max = group.Max(e => e.Obsolete.HasValue && e.Obsolete > e.Creation
|
||||
? e.Obsolete.Value
|
||||
: e.Creation),
|
||||
});
|
||||
return null;
|
||||
//var specDiscriminatorEqual = new DiscriminatorEqualSpec<ChangeLog>(idDiscriminator);
|
||||
//var evaluator =
|
||||
// SpecificationEvaluator.Default
|
||||
//var query = db.Set<ChangeLog>()
|
||||
// //.Where(e => e.IdDiscriminator == idDiscriminator)
|
||||
// .GroupBy(e => 1)
|
||||
// .WithSpecification(specDiscriminatorEqual)
|
||||
// .Select(group => new
|
||||
// {
|
||||
// Min = group.Min(e => e.Creation),
|
||||
// Max = group.Max(e => e.Obsolete.HasValue && e.Obsolete > e.Creation
|
||||
// ? e.Obsolete.Value
|
||||
// : e.Creation),
|
||||
// });
|
||||
|
||||
var values = await query.FirstOrDefaultAsync(token);
|
||||
//var values = await query.FirstOrDefaultAsync(token);
|
||||
|
||||
if (values is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//if (values is null)
|
||||
//{
|
||||
// return null;
|
||||
//}
|
||||
|
||||
return new DatesRangeDto
|
||||
{
|
||||
From = values.Min,
|
||||
To = values.Max,
|
||||
};
|
||||
//return new DatesRangeDto
|
||||
//{
|
||||
// From = values.Min,
|
||||
// To = values.Max,
|
||||
//};
|
||||
}
|
||||
|
||||
private ChangeLogValuesDto Convert(ChangeLog entity) => entity.Adapt<ChangeLogValuesDto>();
|
||||
|
62
DD.Persistence.Database/Repositories/GroupByEvaluator.cs
Normal file
62
DD.Persistence.Database/Repositories/GroupByEvaluator.cs
Normal file
@ -0,0 +1,62 @@
|
||||
using Ardalis.Specification;
|
||||
using Ardalis.Specification.EntityFrameworkCore;
|
||||
using DD.Persistence.Database.Entity;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
using DD.Persistence.Models.Common;
|
||||
|
||||
namespace DD.Persistence.Database.Postgres.Repositories;
|
||||
public class MyPartialEvaluator : IEvaluator
|
||||
{
|
||||
private MyPartialEvaluator() { }
|
||||
public static MyPartialEvaluator Instance { get; } = new MyPartialEvaluator();
|
||||
|
||||
public bool IsCriteriaEvaluator { get; } = true;
|
||||
|
||||
public IQueryable<T> GetQuery<T>(IQueryable<T> query, ISpecification<T> specification) where T : class
|
||||
{
|
||||
|
||||
// Проверяем, есть ли свойство Timestamp в типе T
|
||||
var timestampProperty = typeof(T).GetProperty("Timestamp");
|
||||
|
||||
if (timestampProperty != null && timestampProperty.PropertyType == typeof(DateTimeOffset))
|
||||
{
|
||||
// Если свойство существует и имеет тип DateTime, выполняем группировку и выборку
|
||||
var t = query
|
||||
.GroupBy(x => 1)
|
||||
.Select(group => new
|
||||
{
|
||||
Min = group.Min(e => (DateTimeOffset)timestampProperty.GetValue(e)),
|
||||
Max = group.Max(e => (DateTimeOffset)timestampProperty.GetValue(e)),
|
||||
})
|
||||
.AsQueryable() as IQueryable<T>;
|
||||
return t;
|
||||
}
|
||||
|
||||
return query;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public class Test
|
||||
{
|
||||
public Test()
|
||||
{
|
||||
}
|
||||
|
||||
public DateTimeOffset Min { get; set; }
|
||||
public DateTimeOffset Max { get; set; }
|
||||
}
|
||||
|
||||
public class MySpecificationEvaluator : SpecificationEvaluator
|
||||
{
|
||||
public static MySpecificationEvaluator GroupBy { get; } = new MySpecificationEvaluator();
|
||||
|
||||
private MySpecificationEvaluator() : base()
|
||||
{
|
||||
Evaluators.Add(MyPartialEvaluator.Instance);
|
||||
}
|
||||
}
|
@ -1,4 +1,8 @@
|
||||
using Ardalis.Specification;
|
||||
using Ardalis.Specification.EntityFrameworkCore;
|
||||
using DD.Persistence.Database.Entity;
|
||||
using DD.Persistence.Database.Specifications.Common;
|
||||
using DD.Persistence.Database.Specifications.Common.DiscriminatorItem;
|
||||
using DD.Persistence.Models;
|
||||
using DD.Persistence.Models.Common;
|
||||
using DD.Persistence.Repositories;
|
||||
@ -19,14 +23,16 @@ namespace DD.Persistence.Database.Postgres.Repositories
|
||||
protected virtual IQueryable<Setpoint> GetQueryReadOnly() => db.Set<Setpoint>();
|
||||
|
||||
public async Task<IEnumerable<SetpointValueDto>> GetCurrent(
|
||||
IEnumerable<Guid> setpointKeys,
|
||||
CancellationToken token)
|
||||
IEnumerable<Guid> setpointKeys,
|
||||
CancellationToken token)
|
||||
{
|
||||
var query = GetQueryReadOnly();
|
||||
|
||||
var entities = await query
|
||||
.Where(e => setpointKeys.Contains(e.Key))
|
||||
.GroupBy(e => e.Key)
|
||||
var specDiscriminatorContains = new DiscriminatorContainsSpec<Setpoint>(setpointKeys);
|
||||
|
||||
var entities = await db.Set<Setpoint>()
|
||||
.WithSpecification(specDiscriminatorContains)
|
||||
.GroupBy(e => e.DiscriminatorId)
|
||||
.Select(g => g.OrderByDescending(x => x.Timestamp).FirstOrDefault())
|
||||
.ToArrayAsync(token);
|
||||
|
||||
@ -37,23 +43,27 @@ namespace DD.Persistence.Database.Postgres.Repositories
|
||||
{
|
||||
var query = GetQueryReadOnly();
|
||||
|
||||
var entities = await query
|
||||
.Where(e => setpointKeys.Contains(e.Key))
|
||||
.GroupBy(e => e.Key)
|
||||
var specDiscriminatorContains = new DiscriminatorContainsSpec<Setpoint>(setpointKeys);
|
||||
|
||||
var entities = await db.Set<Setpoint>()
|
||||
.WithSpecification(specDiscriminatorContains)
|
||||
.GroupBy(e => e.DiscriminatorId)
|
||||
.Select(g => g.OrderByDescending(x => x.Timestamp).FirstOrDefault())
|
||||
.ToDictionaryAsync(x=> x.Key, x => (object)x.Value, token);
|
||||
.ToDictionaryAsync(x=> x.DiscriminatorId, x => (object)x.Value, token);
|
||||
|
||||
return entities;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<SetpointValueDto>> GetHistory(IEnumerable<Guid> setpointKeys, DateTimeOffset historyMoment, CancellationToken token)
|
||||
{
|
||||
var query = GetQueryReadOnly();
|
||||
var entities = await query
|
||||
.Where(e => setpointKeys.Contains(e.Key))
|
||||
var specDiscriminatorContains = new DiscriminatorContainsSpec<Setpoint>(setpointKeys);
|
||||
|
||||
var entities = await db.Set<Setpoint>()
|
||||
.WithSpecification(specDiscriminatorContains)
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var filteredEntities = entities
|
||||
.GroupBy(e => e.Key)
|
||||
.GroupBy(e => e.DiscriminatorId)
|
||||
.Select(e => e.OrderBy(o => o.Timestamp))
|
||||
.Select(e => e.Where(e => e.Timestamp <= historyMoment).Last());
|
||||
var dtos = filteredEntities
|
||||
@ -77,31 +87,35 @@ namespace DD.Persistence.Database.Postgres.Repositories
|
||||
|
||||
public async Task<DatesRangeDto> GetDatesRangeAsync(CancellationToken token)
|
||||
{
|
||||
var query = GetQueryReadOnly()
|
||||
|
||||
var spec = new DatesRangeSpec<Setpoint>();
|
||||
var query = db.Set<Setpoint>()
|
||||
.WithSpecification(spec, MySpecificationEvaluator.GroupBy);
|
||||
|
||||
var query2 = GetQueryReadOnly()
|
||||
.GroupBy(e => 1)
|
||||
.Select(group => new
|
||||
{
|
||||
Min = group.Min(e => e.Timestamp),
|
||||
Max = group.Max(e => e.Timestamp),
|
||||
});
|
||||
var values = await query.FirstOrDefaultAsync(token);
|
||||
var result = new DatesRangeDto()
|
||||
{
|
||||
From = values?.Min ?? DateTimeOffset.MinValue,
|
||||
To = values?.Max ?? DateTimeOffset.MaxValue
|
||||
};
|
||||
|
||||
return result;
|
||||
var values = await query.FirstOrDefaultAsync(token);
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<Dictionary<Guid, IEnumerable<SetpointLogDto>>> GetLog(IEnumerable<Guid> setpointKeys, CancellationToken token)
|
||||
{
|
||||
var query = GetQueryReadOnly();
|
||||
var entities = await query
|
||||
.Where(e => setpointKeys.Contains(e.Key))
|
||||
var specDiscriminatorContains = new DiscriminatorContainsSpec<Setpoint>(setpointKeys);
|
||||
|
||||
var entities = await db.Set<Setpoint>()
|
||||
.WithSpecification(specDiscriminatorContains)
|
||||
.ToArrayAsync(token);
|
||||
|
||||
var dtos = entities
|
||||
.GroupBy(e => e.Key)
|
||||
.GroupBy(e => e.DiscriminatorId)
|
||||
.ToDictionary(e => e.Key, v => v.Select(z => z.Adapt<SetpointLogDto>()));
|
||||
|
||||
return dtos;
|
||||
@ -111,7 +125,7 @@ namespace DD.Persistence.Database.Postgres.Repositories
|
||||
{
|
||||
var entity = new Setpoint()
|
||||
{
|
||||
Key = setpointKey,
|
||||
DiscriminatorId = setpointKey,
|
||||
Value = newValue,
|
||||
IdUser = idUser,
|
||||
Timestamp = DateTimeOffset.UtcNow.ToUniversalTime()
|
||||
|
@ -0,0 +1,17 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.ChangeLog;
|
||||
public class CreatedOrUpdatedGeDateSpec<TEntity> : Specification<TEntity>
|
||||
where TEntity : IChangeLog
|
||||
{
|
||||
public CreatedOrUpdatedGeDateSpec(DateTimeOffset date)
|
||||
{
|
||||
Query.Where(e => e.Creation >= date || e.Obsolete >= date);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.ChangeLog;
|
||||
|
||||
/// <summary>
|
||||
/// Спецификация для поиска созданных за определённый период записей IChangeLog
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
public class FromCreationDateRangeSpec<TEntity> : Specification<TEntity>
|
||||
where TEntity : IChangeLog
|
||||
{
|
||||
public FromCreationDateRangeSpec(DateTimeOffset? min, DateTimeOffset? max)
|
||||
{
|
||||
if (min.HasValue)
|
||||
{
|
||||
Query.Where(e => e.Creation >= min);
|
||||
}
|
||||
if (max.HasValue){
|
||||
Query.Where(e => e.Creation <= max);
|
||||
}
|
||||
//Query.Where(e => e.Creation >= min && e.Creation <= max);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.ChangeLog;
|
||||
|
||||
/// <summary>
|
||||
/// Спецификация для поиска исторических записей IChangeLog за определённый период
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
public class FromObsoleteDateRangeSpece<TEntity> : Specification<TEntity>
|
||||
where TEntity : IChangeLog
|
||||
{
|
||||
public FromObsoleteDateRangeSpece(DateTimeOffset min, DateTimeOffset max)
|
||||
{
|
||||
Query.Where(e => e.Obsolete != null && e.Obsolete >= min && e.Obsolete <= max);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.ChangeLog;
|
||||
|
||||
/// <summary>
|
||||
/// Спецификация для поиска записей IChangeLog по массиву ключей
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
public class IdContainsSpec<TEntity> : Specification<TEntity>
|
||||
where TEntity : IChangeLog
|
||||
{
|
||||
public IdContainsSpec()
|
||||
{
|
||||
|
||||
}
|
||||
public IdContainsSpec(IEnumerable<Guid> ids)
|
||||
{
|
||||
Query.Where(s => ids.Contains(s.Id));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.ChangeLog;
|
||||
|
||||
/// <summary>
|
||||
/// Спецификация для актуальных значений IChangeLog
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
public class ObsoleteIsNullSpec<TEntity> : Specification<TEntity>
|
||||
where TEntity : IChangeLog
|
||||
{
|
||||
public ObsoleteIsNullSpec()
|
||||
{
|
||||
Query.Where(e => e.Obsolete == null);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.ChangeLog;
|
||||
|
||||
/// <summary>
|
||||
/// Спецификация для поиска не актуальных значений IChangeLog
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity"></typeparam>
|
||||
public class ObsoleteNotNullSpec<TEntity> : Specification<TEntity>
|
||||
where TEntity : IChangeLog
|
||||
{
|
||||
public ObsoleteNotNullSpec()
|
||||
{
|
||||
Query.Where(e => e.Obsolete != null);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,19 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.Common;
|
||||
|
||||
public class DatesRangeSpec<TEntity> : Specification<TEntity>
|
||||
where TEntity : IDiscriminatorItem
|
||||
{
|
||||
public DatesRangeSpec()
|
||||
{
|
||||
//Query;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.Common.DiscriminatorItem;
|
||||
public class DiscriminatorContainsSpec<TEntity> : Specification<TEntity>
|
||||
where TEntity : IDiscriminatorItem
|
||||
{
|
||||
public DiscriminatorContainsSpec(IEnumerable<Guid> discriminatorIds)
|
||||
{
|
||||
Query.Where(e => discriminatorIds.Contains(e.DiscriminatorId));
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
using Ardalis.Specification;
|
||||
using DD.Persistence.Database.EntityAbstractions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Microsoft.EntityFrameworkCore.DbLoggerCategory;
|
||||
|
||||
namespace DD.Persistence.Database.Specifications.Common.DiscriminatorItem;
|
||||
public class DiscriminatorEqualSpec<TEntity> : Specification<TEntity>
|
||||
where TEntity : IDiscriminatorItem
|
||||
{
|
||||
public DiscriminatorEqualSpec(Guid discriminatorId)
|
||||
{
|
||||
Query.Where(e => e.DiscriminatorId == discriminatorId);
|
||||
}
|
||||
}
|
@ -102,7 +102,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
||||
var result = await client.Add(idDiscriminator, dto, new CancellationToken());
|
||||
|
||||
var entity = dbContext.ChangeLog
|
||||
.Where(x => x.IdDiscriminator == idDiscriminator)
|
||||
.Where(x => x.DiscriminatorId == idDiscriminator)
|
||||
.FirstOrDefault();
|
||||
dto = entity.Adapt<ChangeLogValuesDto>();
|
||||
|
||||
@ -318,7 +318,7 @@ public class ChangeLogControllerTest : BaseIntegrationTest
|
||||
var entities = dtos.Select(d =>
|
||||
{
|
||||
var entity = d.Adapt<ChangeLog>();
|
||||
entity.IdDiscriminator = idDiscriminator;
|
||||
entity.DiscriminatorId = idDiscriminator;
|
||||
entity.Creation = DateTimeOffset.UtcNow.AddDays(generatorRandomDigits.Next(minDayCount, maxDayCount));
|
||||
|
||||
return entity;
|
||||
|
Loading…
Reference in New Issue
Block a user