我有一个简单的应用程序,它可以从以下批次的已售票中注册collection
的款项
驱动程序(领域专家称为settlements
)。我尝试使用DDD方法和EF Core来处理这个小型应用程序(称其为在DDD中使用EF Core的游乐场)。我在SQL Server中基本上有3个表(简化为绝对最小值):
Table: Collection
-------------+---------
Column | Type
-------------+---------
CollectionId | int (PK)
IsCancelled | bit
Table: Settlement
-------------+---------
Column | Type
-------------+---------
SettlementId | int (PK)
CollectionId | int (FK)
Number | int
Table: CollectionSettlementJoin
-------------+---------
Column | Type
-------------+---------
SettlementId | int (PK)(FK)
CollectionId | int (PK)(FK)
我知道似乎有一个冗余的联接表(因为我在CollectionId
表上有Settlement
),但这似乎是设计要求,我将在稍后解释。因此,每个collection
至少具有1个或更多settlements
。我有2个实际上与表相对应的域实体-我的聚合根Collection
并附加到包含Settlements
实体列表的Settlement
属性中。
额外的表用于审计目的,因为实际上并不真正参与该域。它由Settlement.CollectionId
更新时的触发器填充(对于非null)。每个collection
可以在创建后的5分钟内被创建者取消,也可以由超级用户随时取消。取消collection
时,我想将Settlement.CollectionId
重置为null
(发生这种情况时,CollectionSettlementJoin
中的数据保持不变,我总能取回取消的结算)。 / p>
创建collection
时,我当前的设置工作正常。所选的settlements
已添加,保存并成功保存在我的数据库中。当我想取消收藏时,问题就开始了。我从数据库中获取了带有附件collection
的{{1}}。但是,当我从聚合根中删除settlements
时,settlements
不会保留更改(不会将dbContext.SaveChanges()
设置为Settlement.CollectionId
)。
这是我的设置:
null
public class Collection : EntityBase, IAggregateRoot
{
private Collection() { }
public Collection(List<Settlement> settlements)
{
_settlements = settlements;
}
private bool _isCancelled;
public bool IsCancelled => _isCancelled;
private List<Settlement> _settlements;
public IReadOnlyCollection<Settlement> Settlements => _settlements.AsReadOnly();
public void CancelCollection()
{
if (_isCancelled != true)
{
_isCancelled = true;
_settlements.Clear();
}
}
}
public class Settlement : EntityBase
{
private Settlement() { }
public Collection? Collection { get;set; }
public int? CollectionId { get; internal set; }
}
public class CollectionEntityTypeConfiguration : IEntityTypeConfiguration<Collection>
{
public void Configure(EntityTypeBuilder<Collection> builder)
{
builder.ToTable("Collection");
builder.HasKey(s => s.Id);
builder.Property(s => s.Id).HasColumnName("CollectionId").UseIdentityColumn();
builder.Property(s => s.IsCancelled).HasDefaultValueSql("(0)");
builder.HasMany(s => s.Settlements)
.WithOne(c => c.Collection)
.HasForeignKey(s => s.CollectionId);
}
}
上下文(此处不多)
public class SettlementEntityTypeConfiguration : IEntityTypeConfiguration<Settlement>
{
public void Configure(EntityTypeBuilder<Settlement> builder)
{
builder.ToTable("Settlement");
builder.HasKey(s => s.Id);
builder.Property(s => s.Id).HasColumnName("SettlementId").ValueGeneratedNever();
builder.Property(s => s.CollectionId);
builder.HasOne(s => s.Collection)
.WithMany(c => c.Settlements)
.HasForeignKey(s => s.CollectionId);
}
}
最后是我的命令:
public class SettlementCollectionContext: DbContext
{
public SettlementCollectionContext(
DbContextOptions<SettlementCollectionContext> options) : base(options)
{
ChangeTracker.StateChanged += ChangeTracker_StateChanged;
}
private void ChangeTracker_StateChanged(object sender, EntityStateChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine($"Entity {e.Entry.Entity.GetType().Name} has changed.");
}
public DbSet<Collection> Collections { get; set; }
public DbSet<Settlement> Settlements { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new SettlementEntityTypeConfiguration());
modelBuilder.ApplyConfiguration(new CollectionEntityTypeConfiguration());
}
}
我知道var collection = await _dbContext.Collections
.Include(c => c.Settlements)
.Where(c => c.Id == collectionId)
.SingleOrDefaultAsync();
if (!collection!.IsCancelled)
{
collection.CancelCollection();
}
_dbContext.Update(collection); //without this the change tracker does not register the change
_dbContext.SaveChanges();
注册了此更改,因为我在上下文中向ChangeTracker
添加了一个偶数处理程序,并且在调试过程中我注意到它注册了ChangeTracker.StateChanged
已更改(尽管collection
)。我还尝试通过settlement
方法将Settlement.CollectionId
属性重置为null
,但这也没有帮助。我一定很想念东西。
答案 0 :(得分:1)
因此最后,设置没有问题。实际上,我的工作单元存在问题,因为它保存了错误的上下文,因此很明显,这些更改永远不会持久。