EF里一对一、一对多、多对多关系的配置和级联删除
2016-09-28 15:23
369 查看
http://www.cnblogs.com/oppoic/p/ef_one-to-one_one-to-many_many-to-many_cascadedelete.html
本章节开始了解EF的各种关系。如果你对EF里实体间的各种关系还不是很熟悉,可以看看我的思路,能帮你更快的理解。
I.实体间一对一的关系
添加一个PersonPhoto类,表示用户照片类
View Code
直接复制到数据库执行查询,发现它会返回一条主表数据和两条相关联的从表数据。除非必须查出外键记录才使用Include贪婪加载,否则千万不要,EF中跟手写ado不一样,很容易生成很冗余的sql。这里其实只需要主键的记录就可以了,修改下方法:
监控的sql干干净净,只会查出主表数据。
补充:这里只查一条记录却使用SELECT TOP (2)... 是保证能查到记录。
删除sql更干净,只删除主表数据,相关联的从表数据删除由数据库级联删除完成:
级联删除虽然方便,但是并不常用。试想我们在博客园写了很多随笔,为不同随笔加了不同的标签好区分和管理。某一天突然发现之前定的某个标签并不合理,但是这个标签已经在很多随笔里用了,如果此时删除标签,数据库级联的把标注此标签的随笔都删了,这个肯定不合适。应该是标签删了,之前贴过此标签的文章没了这个标签,这个才符合逻辑。
数据库里可以可视化的设置不级联删除,Fluent API配置此外键关系时可以设置不级联删除:
再跑下程序,去看下数据库本外键自然就没了级联删除。
园友郭明锋提供了一个很好的建议:考虑到EF中的级联删除并不常用,所以可以在全局里关掉所有主外键关系的级联删除,如果需要可以打开某个主外键的级联删除。
ok,本文就到此结束,后续还有更通俗易懂的文章介绍EF,请保持关注。本章源码
本章节开始了解EF的各种关系。如果你对EF里实体间的各种关系还不是很熟悉,可以看看我的思路,能帮你更快的理解。
I.实体间一对一的关系
添加一个PersonPhoto类,表示用户照片类
View Code
直接复制到数据库执行查询,发现它会返回一条主表数据和两条相关联的从表数据。除非必须查出外键记录才使用Include贪婪加载,否则千万不要,EF中跟手写ado不一样,很容易生成很冗余的sql。这里其实只需要主键的记录就可以了,修改下方法:
//级联删除(仅加载主键记录) private static void DeleteDestinationInMemeryAndDbCascade() { int destinationId; using (var context = new CodeFirst.DataAccess.BreakAwayContext()) { var destination = new CodeFirst.Model.Destination { Name = "Sample Destination", Lodgings = new List<CodeFirst.Model.Lodging> { new CodeFirst.Model.Lodging {Name="Lodging One"}, new CodeFirst.Model.Lodging {Name="Lodging Two"} } }; context.Destinations.Add(destination); context.SaveChanges(); destinationId = destination.DestinationId; } using (var context = new CodeFirst.DataAccess.BreakAwayContext()) { var destination = context.Destinations .Single(d => d.DestinationId == destinationId); //只取一条主键记录 context.Destinations.Remove(destination); //然后移除主键记录,外键记录又数据库级联删除 context.SaveChanges(); } }
监控的sql干干净净,只会查出主表数据。
exec sp_executesql N'SELECT TOP (2) [Extent1].[DestinationId] AS [DestinationId], [Extent1].[Name] AS [Name], [Extent1].[Country] AS [Country], [Extent1].[Description] AS [Description], [Extent1].[image] AS [image] FROM [dbo].[Destinations] AS [Extent1] WHERE [Extent1].[DestinationId] = @p__linq__0',N'@p__linq__0 int',@p__linq__0=1
补充:这里只查一条记录却使用SELECT TOP (2)... 是保证能查到记录。
删除sql更干净,只删除主表数据,相关联的从表数据删除由数据库级联删除完成:
exec sp_executesql N'delete [dbo].[Destinations] where ([DestinationId] = @0)',N'@0 int',@0=1
级联删除虽然方便,但是并不常用。试想我们在博客园写了很多随笔,为不同随笔加了不同的标签好区分和管理。某一天突然发现之前定的某个标签并不合理,但是这个标签已经在很多随笔里用了,如果此时删除标签,数据库级联的把标注此标签的随笔都删了,这个肯定不合适。应该是标签删了,之前贴过此标签的文章没了这个标签,这个才符合逻辑。
数据库里可以可视化的设置不级联删除,Fluent API配置此外键关系时可以设置不级联删除:
this.HasMany(d => d.Lodgings).WithRequired(l => l.Destination) .Map(l => l.MapKey("DestinationId")) //一对多并指定外键名 .WillCascadeOnDelete(false); // 关闭级联删除
再跑下程序,去看下数据库本外键自然就没了级联删除。
园友郭明锋提供了一个很好的建议:考虑到EF中的级联删除并不常用,所以可以在全局里关掉所有主外键关系的级联删除,如果需要可以打开某个主外键的级联删除。
@郭明锋:好文章,很久没有看到这么好的EF文章了,推荐
EF默认开启级联删除,确实是挺操蛋的设置,所以我的做法是在上下文的OnModelCreating方法中
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
移除这个默认约定,再在需要开启级联删除的FluentAPI关系映射中用. WillCascadeOnDelete(true) 单独开启
EF默认开启级联删除,确实是挺操蛋的设置,所以我的做法是在上下文的OnModelCreating方法中
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
移除这个默认约定,再在需要开启级联删除的FluentAPI关系映射中用. WillCascadeOnDelete(true) 单独开启
ok,本文就到此结束,后续还有更通俗易懂的文章介绍EF,请保持关注。本章源码
相关文章推荐
- EF里一对一、一对多、多对多关系的配置和级联删除
- EF里一对一、一对多、多对多关系的配置和级联删除 - lonelyxmas
- EF里一对一、一对多、多对多关系的配置和级联删除
- EF里一对一、一对多、多对多关系的配置和级联删除
- EF里一对一、一对多、多对多关系的配置和级联删除
- EF里一对一、一对多、多对多关系的配置和级联删除
- EF里一对一、一对多、多对多关系的配置和级联删除
- 【EF Code First】 一对多、多对多的多重关系配置
- EF 关系规则(一对一、一对多、多对多...)
- 【EF Code First】 一对一、一对多的多重关系配置
- EF 一对一、一对多、多对多配置语句小记
- 如何使用EF优雅的配置一对一的关系
- EF 一对一,一对多,多对多 Flunt API 配置
- Hibernate的映射关系与级联(一对一、一对多、多对多)
- Hibernate 关系配置(一对一,一对多)
- jpa的复合主键中关系中如何配置才能做到级联删除,我现在的问题是现在有一个学生类一个课程类,下面补充
- CodeFirst 关系创建——Fluent API配置多重关系,关闭级联删除的方法
- 如何使用EF优雅的配置一对一的关系
- Hibernate关联关系配置(一对多、一对一和多对多)
- hibernate 笔记001---一对多,多对一,多对多,一对一关系汇总