/
afanasevn
/
PdfEncoder
Обзор
Документация
Войти
/
afanasevn
/
PdfEncoder
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/PdfEncoder.Infrastructure/Persistence/PdfEncoderDbContext.cs
109 строк
4 KB
IBS\NAfanasev
Field validation, integration tests, UI polish
06 июл 2026, 17:18
06 июл 2026, 17:18
0e936b0
Код
Авторство
О чём код?
using System.Text.Json; using System.Text.Json.Serialization; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; using PdfEncoder.Domain.Enums; using PdfEncoder.Domain.Models; using PdfEncoder.Infrastructure.Persistence.Entities; namespace PdfEncoder.Infrastructure.Persistence; /// <summary> /// JSON converters для jsonb колонок EF. /// </summary> internal static class JsonColumnConverters { internal static readonly JsonSerializerOptions SerializerOptions = new() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, Converters = { new JsonStringEnumConverter(JsonNamingPolicy.CamelCase) } }; /// <summary> /// Создаёт converter для типа <typeparamref name="T"/>. /// </summary> internal static ValueConverter<T, string> CreateConverter<T>() where T : class { return new ValueConverter<T, string>( value => JsonSerializer.Serialize(value, SerializerOptions), value => JsonSerializer.Deserialize<T>(value, SerializerOptions)!); } } /// <summary> /// EF Core DbContext PdfEncoder. /// </summary> public sealed class PdfEncoderDbContext(DbContextOptions<PdfEncoderDbContext> options) : DbContext(options) { /// <summary> /// Jobs документов. /// </summary> public DbSet<DocumentJobEntity> DocumentJobs => Set<DocumentJobEntity>(); /// <summary> /// Результаты парсинга. /// </summary> public DbSet<ParseResultEntity> ParseResults => Set<ParseResultEntity>(); /// <summary> /// LLM usage logs. /// </summary> public DbSet<LlmUsageLogEntity> LlmUsageLogs => Set<LlmUsageLogEntity>(); /// <inheritdoc /> protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<DocumentJobEntity>(entity => { entity.ToTable("document_jobs"); entity.HasKey(job => job.Id); entity.HasIndex(job => job.ContentHash).IsUnique(); entity.HasIndex(job => job.CreatedAt); entity.Property(job => job.ContentHash).HasMaxLength(64).IsRequired(); entity.Property(job => job.OriginalFileName).HasMaxLength(512).IsRequired(); entity.Property(job => job.DocumentType).HasMaxLength(64).IsRequired(); entity.Property(job => job.Language).HasMaxLength(8).IsRequired(); entity.Property(job => job.Status).HasConversion<string>().HasMaxLength(32); entity.Property(job => job.PdfKind).HasConversion<string?>().HasMaxLength(32); entity.Property(job => job.ErrorCode).HasMaxLength(64); entity.Property(job => job.ErrorMessage).HasMaxLength(2000); }); modelBuilder.Entity<ParseResultEntity>(entity => { entity.ToTable("parse_results"); entity.HasKey(result => result.Id); entity.HasIndex(result => result.DocumentJobId).IsUnique(); entity.Property(result => result.DetectedDocumentType).HasMaxLength(64).IsRequired(); var resultJsonProperty = entity.Property(result => result.ResultJson) .HasConversion(JsonColumnConverters.CreateConverter<GenericParseResult>()); var rawContextProperty = entity.Property(result => result.RawContextJson) .HasConversion(JsonColumnConverters.CreateConverter<DocumentContext>()); if (Database.IsNpgsql()) { resultJsonProperty.HasColumnType("jsonb"); rawContextProperty.HasColumnType("jsonb"); } entity.HasOne(result => result.DocumentJob) .WithOne(job => job.ParseResult) .HasForeignKey<ParseResultEntity>(result => result.DocumentJobId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity<LlmUsageLogEntity>(entity => { entity.ToTable("llm_usage_logs"); entity.HasKey(log => log.Id); entity.HasIndex(log => log.DocumentJobId); entity.Property(log => log.StepName).HasMaxLength(64).IsRequired(); entity.Property(log => log.ModelName).HasMaxLength(128).IsRequired(); entity.HasOne(log => log.DocumentJob) .WithMany(job => job.LlmUsageLogs) .HasForeignKey(log => log.DocumentJobId) .OnDelete(DeleteBehavior.Cascade); }); } }