首页 > 代码库 > EF实体框架之CodeFirst六
EF实体框架之CodeFirst六
上午的时候把复杂类型学习了一下,想着趁着周六日把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<City> 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<Role> Roles { get; set; } }
public class Role { public int RoleId { get; set; } public string Name { get; set; } public virtual List<User> Users { get; set; } }
通过导航属性,Code First会默认生成一个中间表,来表示两个的多对多关系。
Entity Framework Code First根据默认约定生成的多对多关联关系的表时,默认启用多对多的数据级联删除,可以添加代码进行禁用。
protected override void OnModelCreating(DbModelBuilder modelBuilder) { // 禁用多对多关系表的级联删除 modelBuilder.Conventions.Remove<ManyToManyCascadeDeleteConvention>(); }
EF实体框架之CodeFirst六