using MediatR; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; using Vortex.Shared.Kernel; using Vortex.Modules.Identity.Domain; using Vortex.Modules.Identity.Application.Abstractions; namespace Vortex.Modules.Identity.Infrastructure.Persistence; /// /// Контекст базы данных для модуля Identity. /// public sealed class IdentityDbContext : DbContext, IIdentityUnitOfWork { private readonly IMediator _mediator; public IdentityDbContext(DbContextOptions options, IMediator mediator) : base(options) { _mediator = mediator; } public DbSet Users => Set(); public DbSet Stories => Set(); public DbSet StoryViewers => Set(); public DbSet Friendships => Set(); protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); optionsBuilder.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning)); } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.HasDefaultSchema("identity"); modelBuilder.Entity(builder => { builder.ToTable("Friendships"); builder.HasKey(f => f.Id); builder.HasIndex(f => new { f.UserId, f.FriendId }).IsUnique(); }); modelBuilder.Entity(builder => { builder.ToTable("Stories"); builder.HasKey(s => s.Id); builder.Property(s => s.Type).IsRequired(); builder.HasMany(s => s.Viewers) .WithOne() .HasForeignKey(v => v.StoryId) .OnDelete(DeleteBehavior.Cascade); }); modelBuilder.Entity(builder => { builder.ToTable("StoryViewers"); builder.HasKey(v => v.Id); builder.HasIndex(v => new { v.StoryId, v.UserId }).IsUnique(); }); modelBuilder.Entity(builder => { builder.ToTable("Users"); builder.HasKey(u => u.Id); builder.Property(u => u.Username).IsRequired().HasMaxLength(50); builder.HasIndex(u => u.Username).IsUnique(); builder.Property(u => u.PasswordHash).IsRequired(); builder.Property(u => u.DisplayName).HasMaxLength(100); builder.Property(u => u.Email).HasMaxLength(255); builder.Property(u => u.Bio).HasMaxLength(500); builder.Property(u => u.Avatar).HasMaxLength(500); builder.Property(u => u.Birthday); builder.Property(u => u.CreatedAt).IsRequired(); builder.Property(u => u.HideStoryViews).HasDefaultValue(false); }); } public override async Task SaveChangesAsync(CancellationToken cancellationToken = default) { var domainEvents = ChangeTracker .Entries() .SelectMany(x => { if (x.Entity is AggregateRoot root) { var events = root.GetDomainEvents().ToList(); root.ClearDomainEvents(); return events; } return Enumerable.Empty(); }) .ToList(); int result = await base.SaveChangesAsync(cancellationToken); foreach (var domainEvent in domainEvents) { await _mediator.Publish(domainEvent, cancellationToken); } return result; } }