DDD:使用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了。

備注

考慮到聚合內非聚合根的實體都具有“本地標識”,采用“雙主鍵”就非常合理了,這個錯誤新手經常犯的。

再說一個題外話,聚合內的實體的標識能被其它聚合引用嗎?我覺得應該是可以的,前提是必須同時引用其完整的標識,即:雙主鍵。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM