博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF-CodeFirst-3搞事
阅读量:5905 次
发布时间:2019-06-19

本文共 3489 字,大约阅读时间需要 11 分钟。

 

 

本文学习旺杰兄的  系列教程而写。尽量摆脱之前的影子写出自己的理解

表间关系、级联删除

简单玩法已经走通了,但是我就是想搞点事出来。今天来搞搞表间关系和级联删除

 

表间关系

毫无疑问在设计表的时候,对于两张有关联的表,我们要做一对一或一对多的外键关系。这样在使用EF的时候可以轻松的使用导航属性不说,也使得表结构更加简单明朗。使用CodeFirst我们该如何配置呢?

一对一

我们这边有这样两个实体。User、UserCard。 一个用户肯定只会拥有一个身份证号、而一个身份证号肯定也只能属于一个人。这就是一个典型的一对一关系。

[Table("T_User")]    public class User    {        public User()        {            UserId = new Guid(Guid.NewGuid().ToString("D")); ;        }        [Key]        public Guid UserId { get; set; }        [Required]        [MaxLength(20)]        public string Name { get; set; }        [Timestamp]        public byte[] RowVersion { get; set; }        public List
UserRoles { get; set; } ///
/// 扩展 /// public UserAddress UserAddress { get; set; } ///
/// 一个用户拥有一个身份证 /// public UserCard UserCard { get; set; } }

 

///     /// 用户证件实体    ///     [Table("T_User_Card")]    public class UserCard    {        public UserCard()        {            UserId = new Guid(Guid.NewGuid().ToString("D"));        }        [Key]        public Guid UserId { get; set; }        [MaxLength(18)]        public string IdCard { get; set; }        //一个证件只能属于一个人..一对一         public User User { get; set; }    }

之前也提到,配置映射有两种方式。写说注解的方式,很简单。使用ForeignKey()的方式可以轻松的搞定

[Key,ForeignKey("User")]        public Guid UserId { get; set; }

但是在实际开发中大多会用Fluent Api 这个配置也很容易

HasRequired(u => u.User).WithOptional(u => u.UserCard);

 

对关系的配置做一下梳理

Has方法:

  • HasOptional: 前者包含后者一个实例  (可为null)
  • HasRequired:前者包含后者一个不为null的实例
  • HasMany:前者包含后者实例的集合

With方法

  • withOptional:后者包含前者一个实例 (可为null)
  • withRequired:后者包含前者一个不为null的实例
  • withMany:后者包含前者实例的集合

我们的Fluent Api的配置可以清楚的看出来是 UserCard包含一个User不为null的实例而User包含一个UserCard可为null的实例

 

这里记录本人不是很推荐的写法

public class UserCardMap : EntityTypeConfiguration
{ public UserCardMap() { //不推荐的写法 HasRequired(u => u.User).WithMany().HasForeignKey(u => u.UserId); } }

首先我们搞了一个UserId做为外建,使用了Fluent Api做配置映射,下面指定了UserId为外建。看看我们数据库中的关系图是佬样的吧。下图可以看到建立了两个关系 一个UserCard中的Id为主键而User表中生成了一个UserDard_Id为外键。下面则是使用了User表中的主键 User_Card表中的UserId做为外建 。 这样看起来是双向的一对一的关系。好吧,我不需要这样的配置。复杂,而且WithMany看起来像是一对多一样

 

一对多

之前的User和UserRole就是一对多关系,当时并没有做什么。EF为我们自动做了配置,且在UserRole表中添加了User_UserId做外键。这样虽然爽,但是!我就是想让外键叫UserId。这要怎么做呢?当然简单了。。

这是在UserRole中进行配置,代表UserRole拥有一个不为null的User实例,User拥有UserRole的集合。MayKey指定外键名为UserId

HasRequired(o => o.User).WithMany(u => u.UserRoles).Map(o => o.MapKey("UserId"));

Updata-database一下就可以看到表的变化了,UserId做为了外键

 

多对多

多对多关系,开发中经常会用到。我们的User与UserRole之前是一对多的关系。但是如果我们再去细想。一个角色 (老师、公民、程序员) 可以属于多个人。而一个人也可以同时拥有这些角色。这就是一个明显的多对多(-.-之前欠考虑了)。那么要改造成多对多的关系。首先把UserRole表中的User改成list集合

我们在数据库建表的时候遇到多对多关系,一般都会建立一个中间表用来存放两张表的记录。在CodeFirst中我们也要进行这样的配置。

//多对多的配置            HasMany(o => o.Users).WithMany(o => o.UserRoles).Map(m =>            {                m.ToTable("T_User_UserRole_Config");                m.MapLeftKey("UserId");                //这里为了区分,把id改成了UserRoleId                m.MapRightKey("UserRoleId");            });

Update-database一下看一下数据库就大功告成了!

 

 

级联删除

表一旦有了关系,那么自然会生出很多事,我们的主从表一旦主表中的数据删除从表的Fluent Api配置如不是optional都会默认级联删除。嗯,因缺斯挺。但是某些业务需求并不允许我们这么做。数据是很宝贵的东西,也是为什么软删除这么流行的原因。即使主表被删除了但是某些从表中的数据很有价值,这时我们就不得不考虑了。正确的做法全局关闭级联删除。在OnModelCreting中添加

//全局关闭级联删除 modelBuilder.Conventions.Remove
();

那么问题又来了,有些从表中的数据真的只要主表中记录被删除就变的毫无价值,存在就是浪费空间的货。这种还是需要级联删除的,我们可以在xxMap中单独为它开启级联删除

//开启级联删除HasRequired(u => u.User).WithOptional(u => u.UserCard).WillCascadeOnDelete(true);

转载地址:http://atcpx.baihongyu.com/

你可能感兴趣的文章
Java私塾: 研磨设计之备忘录模式(Memento)
查看>>
理解call和apply方法
查看>>
异步加载(延迟加载)与同步加载
查看>>
机器学习瓶颈 - 从黑盒白盒之争说起
查看>>
小程序图片上传七牛
查看>>
java交换两个变量值a,b的多钟方法
查看>>
Python中被双下划线包围的魔法方法
查看>>
JAVA核心编程教学
查看>>
Oracle:数据类型对应表
查看>>
洛谷P1349 广义斐波那契数列
查看>>
BZOJ3160 万径人踪灭
查看>>
Okhttp3请求网络开启Gzip压缩
查看>>
pycharm配置mysql数据库连接访问
查看>>
Spring源码学习:第0步--环境准备
查看>>
烂泥:rsync与inotify集成实现数据实时同步更新
查看>>
call & apply
查看>>
学习英语哦
查看>>
第六届蓝桥杯java b组第四题
查看>>
通过TortoiseGIT怎么把本地项目上传到GitHub
查看>>
Python 1 Day
查看>>