背景

在之前的文章中《DDD:使用EntityFramework的话,如果只为聚合根设计仓储,其它实体如何处理?》,我介绍了如何映射聚合以保证其语义,当时的结论是:聚合内除了聚合根之外的实体必须使用多主键,否则删除操作(Order.OrderItems.Remove(1))只会将外键更新为 Null,最开始学习如何使用 EntityFramework 来映射聚合的时候,就纠结这个问题,当时汤雪华大哥就告诉了更新为 Null 就算删除了,当时感觉是接受了,不过没有内化,这篇文章也是为了内化这种思想。

使用多主键映射三级聚合

模型

     public class Level1
{
public virtual int Level1Id { get; set; } public virtual ICollection<Level2> Level2s { get; set; }
} public class Level2
{
public virtual int Level2Id { get; set; }
public virtual int Level1Id { get; set; } public virtual ICollection<Level3> Level3s { get; set; }
} public class Level3
{
public virtual int Level3Id { get; set; }
public virtual int Level2Id { get; set; }
public virtual int Level1Id { get; set; }
}

映射

             modelBuilder.Entity<Level1>()
.HasKey(x => x.Level1Id)
.Property(x => x.Level1Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Level1>()
.HasMany(x => x.Level2s)
.WithRequired()
.HasForeignKey(x => x.Level1Id)
.WillCascadeOnDelete(); modelBuilder.Entity<Level2>()
.HasKey(x => new { x.Level2Id, x.Level1Id })
.Property(x => x.Level2Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
modelBuilder.Entity<Level2>()
.HasMany(x => x.Level3s)
.WithRequired()
.HasForeignKey(x => new { x.Level2Id, x.Level1Id })
.WillCascadeOnDelete(); modelBuilder.Entity<Level3>()
.HasKey(x => new { x.Level3Id, x.Level2Id, x.Level1Id })
.Property(x => x.Level3Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

测试添加

             for (var i = ; i <= ; i++)
{
var l1 = new Level1
{
Level2s = new List<Level2>
{
new Level2
{
Level3s = new List<Level3>
{
new Level3()
}
}
}
};
context.Level1s.Add(l1);
context.SaveChanges();
}

测试删除

             using (var context = new StudyContext())
{
context.Level1s.First().Level2s.First().Level3s.Clear(); context.SaveChanges();
}

说明

因为采用了多主键,所以 context.Level1s.First().Level2s.First().Level3s.Clear() 会真正的生成 delete 语句,否则只会把外键更新为 null,但是多主键感觉真是不爽,两级还可以接受。

多主键映射这种风格可以导致“物理删除”,单主键这种风格可以导致“逻辑删除”。

如果是逻辑删除,需要注意哪些事项?

  1. 确定何时物理删除?如何物理删除?可以后台自动根据配置的元数据定时物理删除。
  2. 报表查询的时候注意查询语句。

为啥不用级联删除?

级联删除是解决:rep.delete(order),双主键是解决:order.OrderItems.Clear()。

备注

前几天我还暗自高兴找到了“物理删除”的映射方式,今天又更喜欢“逻辑删除”了,害苦了我一位兄弟,他都是用的 “双主键”。

EntityFramework:再谈 “如何映射聚合?”的更多相关文章

  1. Hibernate:如何映射聚合?

    Hibernate:如何映射聚合? 目录 背景映射聚合聚合模型映射配置测试备注 背景返回目录 DDD 是在 Hibernate 之后发现的概念,Hibernate 如何映射 DDD 中的聚合呢?本文给 ...

  2. 再谈angularJS数据绑定机制及背后原理—angularJS常见问题总结

    这篇是对angularJS的一些疑点回顾,是对目前angularJS开发的各种常见问题的整理汇总.如果对文中的题目全部了然于胸,觉得对整个angular框架应该掌握的七七八八了.希望志同道合的通知补充 ...

  3. 再谈HTTP2性能提升之背后原理—HTTP2历史解剖

    即使千辛万苦,还是把网站升级到http2了,遇坑如<phpcms v9站http升级到https加http2遇到到坑>. 因为理论相比于 HTTP 1.x ,在同时兼容 HTTP/1.1 ...

  4. 【字符串算法1】 再谈字符串Hash(优雅的暴力)

    [字符串算法1] 字符串Hash(优雅的暴力) [字符串算法2]Manacher算法 [字符串算法3]KMP算法 这里将讲述  [字符串算法1] 字符串Hash 老版原文: RK哈希(Rabin_Ka ...

  5. 再谈JavaScript的数据类型问题

    JavaScript的数据类型问题已经讨论过很多次了,但许多人还有许多书仍然沿用着错误的.混乱的一些观点,所以就再细讲一回. 提及这个讨论的原因在于argb同学在我的MSN博客上的一段回复,又更早的起 ...

  6. 再谈Transaction——MySQL事务处理分析

    MySQL 事务基础概念/Definition of Transaction 事务(Transaction)是访问和更新数据库的程序执行单元;事务中可能包含一个或多个 sql 语句,这些语句要么都执行 ...

  7. [转载]再谈百度:KPI、无人机,以及一个必须给父母看的案例

    [转载]再谈百度:KPI.无人机,以及一个必须给父母看的案例 发表于 2016-03-15   |   0 Comments   |   阅读次数 33 原文: 再谈百度:KPI.无人机,以及一个必须 ...

  8. Support Vector Machine (3) : 再谈泛化误差(Generalization Error)

    目录 Support Vector Machine (1) : 简单SVM原理 Support Vector Machine (2) : Sequential Minimal Optimization ...

  9. Unity教程之再谈Unity中的优化技术

    这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体   这一步主要是为了针对性能瓶颈中的”顶点 ...

随机推荐

  1. POJ 1218 THE DRUNK JAILER(类开灯问题,完全平方数)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2188 题目大意:n为5-100之间的一个数,代表有多少间牢房,刚开始所有房间打开,第一轮2的倍数的房间 ...

  2. Cosbench测试 RGW S3 path_style_access=true模式支持

    使用Ceph RGW Cosbench  测试时,文档中没有写如何使用 path_style_access 模式的方法. 查看了一下cosbench源码发现已经支持,只是文档没有写. 提交了一个iss ...

  3. 湖南省第十一届大学生程序设计竞赛:Internet of Lights and Switches(HASH+二分+异或前缀和)

    Internet of Lights and Switches Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 3  Solved: 3[Submit][ ...

  4. 基于Token的授权(with srping mvc)

    @Override public void doFilter(ServletRequest sr, ServletResponse sr1, FilterChain fc) throws IOExce ...

  5. day6 time和datetime模块

        time模块 time模块提供各种操作时间的函数 #1.时间戳    1970年1月1日之后的秒 #2.元组 包含了:年.日.星期等... time.struct_time #3.格式化的字符 ...

  6. 纯css导航下划线跟随效果【转载】

    css: ul { display: flex; position: absolute; width: 800px; top: 50%; left: 50%; transform: translate ...

  7. SSH 公私钥的基本使用

    SSH 公私钥的基本使用 创建密钥 使用 ssh-keygen 生成公私钥 在终端敲入 ssh-keygen 命令,一路一直按回车下去,会把密钥文件放置在默认路径,也就是 ~/.ssh/ 路径下,并且 ...

  8. 在IIS上运行node

    目录 前言 iisnode web.config 前言 之前自己搞了个域名,然后发现域名默认映射到80端口,腾讯云又没有修改映射端口的功能.然后服务器又是和几个sx一起租的,于是只能想办法把发到80端 ...

  9. 微信小程序开发之路之组件化

    类似于页面,自定义组件拥有自己的 wxml 模版和 wxss 样式. 官方链接 组件化,反过来理解,写重复的页面,方法,写第二遍就烦了,抽取出来就是组件化,可以理解为公用的方法 对于通用的数据,最先想 ...

  10. 网页后门工具laudanum

     网页后门工具laudanum laudanum是Kali Linux预先安装的Web Shell工具.它支持多种Web后台技术,如ASP.ASP.net .JSP.PHP.Coldfusion.它提 ...