ApplicationDbContext 认为 DomainEvent 是一个实体,但它不是
ApplicationDbContext thinks that DomainEvent is an entity but it is not
Using context 'ApplicationDbContext'.
System.InvalidOperationException: The entity type 'DomainEvent' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.
ApplicationDbContext 认为DomainEvent 是一个实体,其实不是。它使我的迁移失败。是什么让它看起来像这样?
public abstract class Entity
{
public int Id { get; set; }
public ICollection<DomainEvent> DomainEvents { get; } = new Collection<DomainEvent>();
public void AddDomainEvent(DomainEvent eventItem)
{
DomainEvents.Add(eventItem);
}
public void RemoveDomainEvent(DomainEvent eventItem)
{
DomainEvents.Remove(eventItem);
}
}
public class Bot : Entity, IAggregateRoot
{
public string Symbol { get; set; }
}
public interface IAggregateRoot
{
}
public abstract class DomainEvent : INotification
{
public DateTime DateOccurred { get; protected set; } = DateTime.UtcNow;
}
public class BotCompletedEvent : DomainEvent
{
public BotCompletedEvent(Bot completedItem)
{
CompletedItem = completedItem;
}
public Bot CompletedItem { get; set; }
}
public class ApplicationDbContext : DbContext, IUnitOfWork
{
private readonly IMediator _mediator;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IMediator mediator)
: base(options)
{
_mediator = mediator;
}
public DbSet<Bot> Bots { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
base.OnModelCreating(modelBuilder);
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
var entitiesWithEvents = ChangeTracker.Entries<Entity>()
.Select(e => e.Entity)
.Where(e => e.DomainEvents.Any())
.ToList();
foreach (var entity in entitiesWithEvents)
{
var events = entity.DomainEvents;
entity.DomainEvents.Clear();
foreach (var domainEvent in events)
{
await _mediator.Publish(domainEvent, cancellationToken).ConfigureAwait(false);
}
}
return await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
}
public override int SaveChanges()
{
return SaveChangesAsync().GetAwaiter().GetResult();
}
}
public interface IUnitOfWork
{
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
只需使用 INotification
作为您的域事件类型。
public ICollection<INotification> DomainEvents { get; } = new Collection<INotification>();
因为它现在是一个接口,所以它会被 EF Core 忽略。参见 Domain events: design and implementation。
Using context 'ApplicationDbContext'.
System.InvalidOperationException: The entity type 'DomainEvent' requires a primary key to be defined. If you intended to use a keyless entity type, call 'HasNoKey' in 'OnModelCreating'. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.
ApplicationDbContext 认为DomainEvent 是一个实体,其实不是。它使我的迁移失败。是什么让它看起来像这样?
public abstract class Entity
{
public int Id { get; set; }
public ICollection<DomainEvent> DomainEvents { get; } = new Collection<DomainEvent>();
public void AddDomainEvent(DomainEvent eventItem)
{
DomainEvents.Add(eventItem);
}
public void RemoveDomainEvent(DomainEvent eventItem)
{
DomainEvents.Remove(eventItem);
}
}
public class Bot : Entity, IAggregateRoot
{
public string Symbol { get; set; }
}
public interface IAggregateRoot
{
}
public abstract class DomainEvent : INotification
{
public DateTime DateOccurred { get; protected set; } = DateTime.UtcNow;
}
public class BotCompletedEvent : DomainEvent
{
public BotCompletedEvent(Bot completedItem)
{
CompletedItem = completedItem;
}
public Bot CompletedItem { get; set; }
}
public class ApplicationDbContext : DbContext, IUnitOfWork
{
private readonly IMediator _mediator;
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options, IMediator mediator)
: base(options)
{
_mediator = mediator;
}
public DbSet<Bot> Bots { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
base.OnModelCreating(modelBuilder);
}
public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken = new())
{
var entitiesWithEvents = ChangeTracker.Entries<Entity>()
.Select(e => e.Entity)
.Where(e => e.DomainEvents.Any())
.ToList();
foreach (var entity in entitiesWithEvents)
{
var events = entity.DomainEvents;
entity.DomainEvents.Clear();
foreach (var domainEvent in events)
{
await _mediator.Publish(domainEvent, cancellationToken).ConfigureAwait(false);
}
}
return await base.SaveChangesAsync(cancellationToken).ConfigureAwait(false);
}
public override int SaveChanges()
{
return SaveChangesAsync().GetAwaiter().GetResult();
}
}
public interface IUnitOfWork
{
Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
}
只需使用 INotification
作为您的域事件类型。
public ICollection<INotification> DomainEvents { get; } = new Collection<INotification>();
因为它现在是一个接口,所以它会被 EF Core 忽略。参见 Domain events: design and implementation。