EntityFramework:「集約のマッピング方法」について

11151 ワード

背景
以前の記事では「DDD:EntityFrameworkを使用する場合、集約ルートのみに倉庫を設計する場合、他のエンティティはどのように処理しますか?」で、集約をどのようにマッピングして意味を保証するかについて説明していましたが、当時の結論は、集約内の集約ルート以外のエンティティはマルチプライマリ・キーを使用する必要があります.そうしないと、削除操作(Order.OrderItems.Remove(1))は外部キーをNullに更新し、EntityFrameworkを使用して集約をマッピングする方法を最初に学習したとき、この問題について、当時湯雪華の長兄はNullに更新して削除しても、受け入れたような気がしたが、内化していなかった.この文章も内化のためだった.
マルチプライマリ・キーを使用した3次集約のマッピング
モデル#モデル#
 1     public class Level1
 2     {
 3         public virtual int Level1Id { get; set; }
 4 
 5         public virtual ICollection<Level2> Level2s { get; set; }
 6     }
 7 
 8     public class Level2
 9     {
10         public virtual int Level2Id { get; set; }
11         public virtual int Level1Id { get; set; }
12 
13         public virtual ICollection<Level3> Level3s { get; set; }
14     }
15 
16     public class Level3
17     {
18         public virtual int Level3Id { get; set; }
19         public virtual int Level2Id { get; set; }
20         public virtual int Level1Id { get; set; }
21     }

マッピング
 1             modelBuilder.Entity<Level1>()
 2                 .HasKey(x => x.Level1Id)
 3                 .Property(x => x.Level1Id)
 4                 .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
 5             modelBuilder.Entity<Level1>()
 6                 .HasMany(x => x.Level2s)
 7                 .WithRequired()
 8                 .HasForeignKey(x => x.Level1Id)
 9                 .WillCascadeOnDelete();
10 
11             modelBuilder.Entity<Level2>()
12                 .HasKey(x => new { x.Level2Id, x.Level1Id })
13                 .Property(x => x.Level2Id)
14                 .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
15             modelBuilder.Entity<Level2>()
16                 .HasMany(x => x.Level3s)
17                 .WithRequired()
18                 .HasForeignKey(x => new { x.Level2Id, x.Level1Id })
19                 .WillCascadeOnDelete();
20 
21             modelBuilder.Entity<Level3>()
22                 .HasKey(x => new { x.Level3Id, x.Level2Id, x.Level1Id })
23                 .Property(x => x.Level3Id)
24                 .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

テストの追加
 1             for (var i = 1; i <= 2; i++)
 2             {
 3                 var l1 = new Level1
 4                 {
 5                     Level2s = new List<Level2>
 6                     { 
 7                         new Level2
 8                         {
 9                             Level3s = new List<Level3>
10                             {
11                                 new Level3()
12                             }
13                         }
14                     }
15                 };
16                 context.Level1s.Add(l1);
17                 context.SaveChanges();
18             }

削除のテスト
1             using (var context = new StudyContext())
2             {
3                 context.Level1s.First().Level2s.First().Level3s.Clear();
4 
5                 context.SaveChanges();
6             }

説明
マルチプライマリキーが採用されているためcontext.Level1s.First().Level2s.First().Level3s.Clear()はdelete文を本当に生成します.そうしないと、外部キーをnullに更新するだけですが、マルチプライマリキーは本当に不快で、2段階は受け入れることができます.
マルチプライマリ・キー・マッピングこのスタイルは、「物理的削除」をもたらし、単一プライマリ・キーのスタイルは「論理的削除」をもたらします.
論理削除の場合、どのような注意事項が必要ですか?
  • 物理的に削除するタイミングを決定しますか?物理的に削除する方法バックグラウンドでは、構成されたメタデータのタイミングに応じて自動的に物理的に削除できます.
  • レポートのクエリー時にクエリー文に注意します.

  • なぜカスケードで削除しないのですか?
    カスケード削除は解決:rep.delete(order)、デュアルプライマリキーは解決:order.OrderItems.Clear().
     
    コメント
    先日私はまたひそかに“物理の削除”のマッピングの方式を探し当てて喜んで、今日また更に“論理の削除”が好きで、私の1人の兄弟を苦しめて、彼はすべて“2つの主な鍵”を使います.