博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
EF实体框架之CodeFirst六
阅读量:5792 次
发布时间:2019-06-18

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

上午的时候把复杂类型学习了一下,想着趁着周六日把Code First学习完,所以下午还是把Code First中的关系学习下。在数据库中最重要的恐怕就是E-R图了,E-R体现了表与表直接的关系。使用Code First也需要把这种表与表直接的关系映射到数据库中,所以关系映射在Code First中也是很重要的一节。Code First中主要包括一对一、一对多、多对多。

一、外键列名默认约定

Entity Framework Code First在根据默认约定创建外键时,外键列的名称存在3种方式:目标类型的键名,目标类型名称+目标类型键名称,引用属性名称+目标类型键名称。为了验证这3种方式创建了两个类:Province省份类、City城市类。

1.目标类型的键名

这种方式为要求在City表中外键列名与Province表中的主键列名相同,所以也就要求在City类中有定义与Province类中作为主键的属性。如在Province类中主键属性为ProvinceId,则需要在City类中也定义一个ProvinceId的属性。

public class Province    {        [Key]        public string  ProvinceId { get; set; }        public string ProvinceName { get; set; }        public virtual ICollection
Citys { get; set; } }
public class City    {        public int CityId { get; set; }        public string CityName { get; set; }        public string ProvinceId { get; set; }    }

还有一点就是看有的博客有的加virtual关键字,有的不加,这两个的区别是什么呢?其实添加virtual关键字主要是为了懒加载,比如在获取Province时,不加virtual则会把Citys也会获取到,而加了virtual时只有在用到的时候才获取。如果在City类的ProvinceId上加[Required]约定,则Province与City就会是级联删除的关系。

2.目标类型名称+目标类型键名称

这种的话就是在City表中映射成Province(类型名称)+ProvinceId(类型键名称)。这种只需在上面的基础上稍作修改就是。即把City类中的ProvinceId属性去掉。

public class City    {        public int CityId { get; set; }        public string CityName { get; set; }    }

3.引用属性名称+目标类型键名称

这种方式为要求在City表中外键列名为在City类中引用Province的属性名称 + Province类的主键名称。如:在City类中定义一个Province属性Pro,则生成的外键名称为Pro_ProvinceId。

public class City    {        public int CityId { get; set; }        public string CityName { get; set; }        [Required]        public Province Pro { get; set; }    }

上面也是加了[Required],也是构成了级联删除。

二、指定外键名

可以使用 [ForeignKey]约定来自定义外键名。

public class City    {        public int CityId { get; set; }        public string CityName { get; set; }               public string ProId { get; set; }        [ForeignKey("ProId")]//ProId一对要存在        public Province Province { get; set; }    }

 三、一对多关系

上面的Province和City就属于一对多的关系。

四、一对一

对于一对一的关系,首先它们要互相引用这是必须的。这还不够,还是会报错,需要设置谁参照谁,哪个是依赖类。

using System;using System.Collections.Generic;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;using System.Linq;using System.Text;using System.Threading.Tasks;namespace EFCodeFirstModels{    public enum SexType { Male, Female }    [Table("Person")]    public class Person    {        [Key]        public string PersonId { get; set; }        //姓名              public string Name { get; set; }        //性别        public SexType Sex { get; set; }        //年龄        public int Age { get; set; }              public virtual IDCard Card { get; set; }    }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.ComponentModel.DataAnnotations;using System.ComponentModel.DataAnnotations.Schema;namespace EFCodeFirstModels{        public class IDCard    {        [Key,ForeignKey("Person")]        public string PersonId { get; set; }        //法定出生日期        public DateTime BirthDate { get; set; }        public virtual  Person Person { get; set; }    }}

五、多对多

 多对多关系用的最多的也举例子最多的恐怕就是用户和角色的关系了。一个用户可以有多个角色,一个角色包含多个用户。

public class User    {        public int UserId { get; set; }        public string Name { get; set; }        public virtual List
Roles { get; set; } }
public class Role    {        public int RoleId { get; set; }        public string Name { get; set; }        public virtual List
Users { get; set; } }

通过导航属性,Code First会默认生成一个中间表,来表示两个的多对多关系。

Entity Framework Code First根据默认约定生成的多对多关联关系的表时,默认启用多对多的数据级联删除,可以添加代码进行禁用。

protected override void OnModelCreating(DbModelBuilder modelBuilder)        {            // 禁用多对多关系表的级联删除            modelBuilder.Conventions.Remove
(); }

 六、对同一个实体多个引用的情况

首先看下下面的数据模型。

public class Person    {        public int PersonID { get; set; }        public string FirstName { get; set; }        public string LastName { get; set; }        public List
PrimaryContactFor { get; set; } public List
SecondaryContactFor { get; set; } }
public class Lodging    {        public int LodgingId { get; set; }        public string Name { get; set; }        public string Owner { get; set; }        public bool IsResort { get; set; }        public decimal MilesFromNearestAirport { get; set; }        //第一联系人        public virtual Person PrimaryContact { get; set; }        //第二联系人        public virtual  Person SecondaryContact { get; set; }    }

Lodging(旅店)有两个对Person表的引用,分别是PrimaryContact与SecondaryContact,同时,在Person表中也有对这两个联系人的导航:PrimaryContactFor与SecondaryContactFor。下面截图是它的映射。

可以看到,Lodings表中一下子有4个外键,这也太多了,因为有两套类型一样的导航属性与引用属性,Code First无法确定它们之间的对应关系,就单独为每个属性都创建了一个关系。这肯定不是我们所期望的,为了让Code First知道它们之间的对应关系,在这里要用到逆导航属性来解决。使用InverseProperty约定。

public class Lodging    {        public int LodgingId { get; set; }        public string Name { get; set; }        public string Owner { get; set; }        public bool IsResort { get; set; }        public decimal MilesFromNearestAirport { get; set; }        //第一联系人        [InverseProperty("PrimaryContactFor")]        public virtual Person PrimaryContact { get; set; }        //第二联系人        [InverseProperty("SecondaryContactFor")]        public virtual  Person SecondaryContact { get; set; }    }

 

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

你可能感兴趣的文章
Scrapy基本用法
查看>>
PAT A1030 动态规划
查看>>
自制一个 elasticsearch-spring-boot-starter
查看>>
【人物志】美团前端通道主席洪磊:一位产品出身、爱焊电路板的工程师
查看>>
一份关于数据科学家应该具备的技能清单
查看>>
机器学习实战_一个完整的程序(一)
查看>>
Web框架的常用架构模式(JavaScript语言)
查看>>
如何用UPA优化性能?先读懂这份报告!
查看>>
这些Java面试题必须会-----鲁迅
查看>>
CSS盒模型
查看>>
ng2路由延时加载模块
查看>>
使用GitHub的十个最佳实践
查看>>
脱离“体验”和“安全”谈盈利的游戏运营 都是耍流氓
查看>>
慎用!BLEU评价NLP文本输出质量存在严重问题
查看>>
JAVA的优势就是劣势啊!
查看>>
ELK实战之logstash部署及基本语法
查看>>
帧中继环境下ospf的使用(点到点模式)
查看>>
BeanShell变量和方法的作用域
查看>>
LINUX下防恶意扫描软件PortSentry
查看>>
由数据库对sql的执行说JDBC的Statement和PreparedStatement
查看>>