使用EntityFramework持久化聚合

目录

背景使用EntityFramework持久化聚合备注

背景返回目录

DDD中只有聚合根可以有仓储,仓储负责整个聚合持久化的相关生命周期,在不使用工作单元或POCO的情况下,我们可以让Order内部直接调用DAL操作OrderItem。我们也可以让Order跟踪所有OrderItem的状态,然后在OrderRepository内部操作OrderItem。如果我们采用了重量级的ORM工具,如:EntityFramework,事情会不会变得简单呢?

使用EntityFramework持久化聚合返回目录

关键思路:双主键。

示例聚合

这里以订单和订单项为例。

Order管理OrderItem

复制代码
 1         public void AddOrderItem(OrderItem item)
 2         {
 3             item.MustNotNull("item");
 4 
 5             this.State.BeforeChangeOrder();
 6 
 7             item.OrderId = this.Id;
 8             this.OrderItemCollection.Add(item);
 9             this.Total += item.Subtotal;
10         }
11 
12         public void RemoveOrderItem(Guid productId)
13         {
14             this.State.BeforeChangeOrder();
15 
16             var item = this.OrderItemCollection.First(x => x.ProductId == productId);
17             this.OrderItemCollection.Remove(item);
18             this.Total -= item.Subtotal;
19         }
复制代码

映射配置

复制代码
 1             modelBuilder
 2                 .Entity<OrderItem>()
 3                 .HasKey(x => new { x.Id, x.OrderId });
 4 
 5             modelBuilder
 6                 .Entity<Order>()
 7                 .HasKey(x => x.Id);
 8             modelBuilder
 9                 .Entity<Order>()
10                 .Property(x => x.OptimisticKey).IsRowVersion().IsConcurrencyToken();
11             modelBuilder
12                 .Entity<Order>()
13                 .HasMany(x => x.OrderItemCollection).WithRequired().HasForeignKey(x => x.OrderId).WillCascadeOnDelete();
复制代码

注意:上面为OrderItem配置了双主键,如果不这么配置,删除逻辑会错误,要么删除后提交失败,要么OrderItem的数据库记录还在,只是OrderId变为NULL了。

备注返回目录

考虑到聚合内非聚合根的实体都具有“本地标识”,采用“双主键”就非常合理了,这个错误新手经常犯的。

再说一个题外话,聚合内的实体的标识能被其它聚合引用吗?我觉得应该是可以的,前提是必须同时引用其完整的标识,即:双主键。

 
分类: DDD
原文地址:https://www.cnblogs.com/Leo_wl/p/3314807.html