Код: Выделить всё
public interface IDomainEvent
{
[NotMapped]
IReadOnlyCollection DomainEvents { get; }
void AddDomainEvent(DomainEvent notificationEvent);
void RemoveDomainEvent(DomainEvent notificationEvent);
void ClearDomainEvents();
}
Код: Выделить всё
public abstract class Entity : IDomainEvent
{
private readonly List _domainEvents = new();
[NotMapped]
public IReadOnlyCollection DomainEvents => _domainEvents.AsReadOnly();
public virtual void AddDomainEvent(DomainEvent newEvent)
{
_domainEvents.Add(newEvent);
}
public virtual void RemoveDomainEvent(DomainEvent eventItem)
{
_domainEvents.Remove(eventItem);
}
public virtual void ClearDomainEvents()
{
_domainEvents.Clear();
}
}
Код: Выделить всё
public class DomainEventOutboxInterceptor : SaveChangesInterceptor
{
public override ValueTask SavingChangesAsync(DbContextEventData eventData, InterceptionResult result,
CancellationToken cancellationToken = new())
{
if (eventData.Context != null)
{
InsertOutboxMessages(eventData.Context);
}
return base.SavingChangesAsync(eventData, result, cancellationToken);
}
private static void InsertOutboxMessages(DbContext dbContext)
{
var domainEvents = dbContext.ChangeTracker.Entries()
.Select(e => e.Entity)
.Where(e => e.DomainEvents.Count != 0)
.SelectMany(e =>
{
var domainEvents = e.DomainEvents.ToList();
e.ClearDomainEvents();
return domainEvents;
})
.ToList();
var outboxMessages = domainEvents.Select(domainEvent => new OutboxMessage
{
Id = Guid.NewGuid(),
Name = domainEvent.GetType().Name,
Content = JsonSerializer.Serialize(domainEvent, domainEvent.GetType()),
CreatedOn = DateTimeOffset.Now,
IsProcessed = false,
ProcessedOn = null,
}).ToList();
if (outboxMessages.Count > 0)
dbContext.Set().AddRange(outboxMessages);
}
}
Код: Выделить всё
public class Post : Entity
{
public Title Title { get; private set; }
public Content Content { get; private set; }
public DateTime CreatedAt { get; private set; }
public Author Author { get; private set; }
private readonly List _comments = new();
public IReadOnlyList Comments => _comments.AsReadOnly();
}
public class PostModel
{
public Guid Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Author { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public ICollection Comments { get; set; } = new List();
}
Код: Выделить всё
PostModel
Как я могу разделить модели домена и базы данных, используя при этом преимущества создания событий домена и исходящего ящика шаблон?
Или вообще, неправильно ли всегда использовать модели предметной области в качестве моделей БД? если нет, то как вы справляетесь с различными конструкциями баз данных?
Подробнее здесь: https://stackoverflow.com/questions/792 ... nt-raising