11.翻译系列:在EF 6中配置一对零或者一对一的关系【EF 6 Code-First系列】

原文链接:https://www.entityframeworktutorial.net/code-first/configure-one-to-one-relationship-in-code-first.aspx

EF 6 Code-First系列文章目录:

  • 1 翻译系列:什么是Code First(EF 6 Code First 系列)
  • 2.翻译系列:为EF Code-First设置开发环境(EF 6 Code-First系列)
  • 3.翻译系列:EF Code-First 示例(EF 6 Code-First系列)
  • 4.翻译系列:EF 6 Code-First默认约定(EF 6 Code-First系列)
  • 5.翻译系列:EF 6中数据库的初始化(EF 6 Code-First 系列)
  • 6.翻译系列:EF 6 Code-First中数据库初始化策略(EF 6 Code-First系列
  • 7.翻译系列:EF 6中的继承策略(EF 6 Code-First 系列)
  • 8.翻译系列: EF 6中配置领域类(EF 6 Code-First 系列)
  • 9.翻译系列:EF 6以及EF Core中的数据注解特性(EF 6 Code-First系列)
  •        9.1 翻译系列:数据注解特性之----Table【EF 6 Code-First 系列】
  •        9.2 翻译系列:数据注解特性之---Column【EF 6 Code First系列】
  •        9.3 翻译系列:数据注解特性之Key【EF 6 Code-First 系列】
  •        9.4 翻译系列:EF 6以及 EF Core中的NotMapped特性(EF 6 Code-First系列)
  •        9.5 翻译系列:数据注解之ForeignKey特性【EF 6 Code-First系列】
  •        9.6 翻译系列:数据注解之Index特性【EF 6 Code-First系列】
  •        9.7 翻译系列:EF数据注解特性之--InverseProperty【EF 6 Code-First系列】
  •        9.8 翻译系列:数据注解特性之--Required 【EF 6 Code-First系列】
  •        9.9 翻译系列:数据注解特性之--MaxLength 【EF 6 Code-First系列】
  •        9.10 翻译系列:EF数据注解特性之StringLength【EF 6 Code-First系列】
  •        9.11 翻译系列:数据注解特性之--Timestamp【EF 6 Code-First系列】
  •        9.12 翻译系列:数据注解特性之ConcurrencyCheck【EF 6 Code-First系列】
  • 10.翻译系列:EF 6中的Fluent API配置【EF 6 Code-First系列】
  •        10.1.翻译系列:EF 6中的实体映射【EF 6 Code-First系列】
  •        10.2.翻译系列:使用Fluent API进行属性映射【EF 6 Code-First】
  • 11.翻译系列:在EF 6中配置一对零或者一对一的关系【EF 6 Code-First系列】
  • 12.翻译系列:EF 6 中配置一对多的关系【EF 6 Code-First系列】
  • 13.翻译系列:Code-First方式配置多对多关系【EF 6 Code-First系列】
  • 14.翻译系列:从已经存在的数据库中生成上下文类和实体类【EF 6 Code-First系列】
  • 15.翻译系列:EF 6中的级联删除【EF 6 Code-First 系列】
  • 16.翻译系列:EF 6 Code -First中使用存储过程【EF 6 Code-First系列】
  • 17.翻译系列:将Fluent API的配置迁移到单独的类中【EF 6 Code-First系列】
  • 18.翻译系列:EF 6 Code-First 中的Seed Data(种子数据或原始测试数据)【EF 6 Code-First系列】
  • 19.翻译系列:EF 6中定义自定义的约定【EF 6 Code-First约定】
  • 20.翻译系列:Code-First中的数据库迁移技术【EF 6 Code-First系列】
  •        20.1翻译系列:EF 6中自动数据迁移技术【EF 6 Code-First系列】
  •        20.2.翻译系列:EF 6中基于代码的数据库迁移技术【EF 6 Code-First系列】
  • 21.翻译系列:Entity Framework 6 Power Tools【EF 6 Code-First系列】

这里,你将学习在两个实体间,配置一对零或者一对多的关系。
我们使用Student和StudentAddress实体来配置这种关系:

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }
}
     
public class StudentAddress 
{
    public int StudentAddressId { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

你可以看这篇文章,Entity Relationship 来理解EF怎么管理一对一、一对多、多对多关系的。

一对零或一对一的关系发生在这样的两个实体之间:当一个表的主键,是另外一个表的主键并且是外键的时候,所以我们需要配置Student实体中的StudentID属性为主键,然后StudentAddressID既是主键又是外键。

使用数据注解配置一对零或一对一关系

这里,我们将使用数据注解特性来给Student实体和StudentAddress实体,配置一对零或者一对一关系。

Student实体遵循默认的约定,它包含一个StudentId属性,所以到时候这个属性就会成为Students表的主键,Student实体我们不用作任何修改,就让它根据默认配置就行。

对于StudentAddress实体,我们需要配置StudentAddressId为主键和外键,因为StudentAddressId遵循约定,所以只用给它配置外键。

public class Student
{
    public int StudentId { get; set; }
    public string StudentName { get; set; }

    public virtual StudentAddress Address { get; set; }
}
     
public class StudentAddress 
{
    [ForeignKey("Student")]
    public int StudentAddressId { get; set; }
        
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public int Zipcode { get; set; }
    public string State { get; set; }
    public string Country { get; set; }

    public virtual Student Student { get; set; }
}

这样就使用数据注解配置了一对零或一对一的关系了。

请注意:Student包含StudentAddress导航属性,并且StudentAddress实体包含Student导航属性。在一对零或一对一关系中,Student可以在没有StudentAddress的情况下被保存,但是StudentAddress没有Student的情况下不能保存。EF将会抛出异常,如果你没有Student实体就保存StudentAddress实体的话。

使用Fluent API配置一对零或者一对一关系

这里我们将使用Fluent API配置一对零或者一对一关系。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure Student & StudentAddress entity
    modelBuilder.Entity()
                .HasOptional(s => s.Address) // Mark Address property optional in Student entity
                .WithRequired(ad => ad.Student); // mark Student property as required in StudentAddress entity. Cannot save StudentAddress without Student
}

上面的例子中,我们从Student实体开始配置,HasOptional()方法配置Student实体中的Address导航属性为可选的【保存Student实体的时候,可以没有StudentAddress实体】,然后WithRequired方法设置StudentAddress实体中的Student导航属性为必须的【保存StudentAddress实体的时候,必须要有Student】。上面的代码,同样会使StudentAddressId成为外键。

这样你就配置了一对零或者一对一的关系,这里Student可以在没有StudentAddress的情况下保存,但是StudentAddress不能在没有Student的情况下保存。EF API将会创建下面的数据库:
11.翻译系列:在EF 6中配置一对零或者一对一的关系【EF 6 Code-First系列】_第1张图片

使用Fluent API配置一对一的关系

我们可以使用Fluent API配置一对一的关系,这样情况下,两个实体对于彼此都是必须的,意味着:Student必须包含StudentAddress,并且StudentAddress必须包含Student。

请注意:SQL Server中,一对一的关系,在技术上是不可能的。上面的代码设置将会永远是一对零或一对一关系。EF只是对实体形成一对一的关系,并不是在数据库中是一对一关系。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity()
                .HasRequired(s => s.Address) 
                .WithRequiredPrincipal(ad => ad.Student); 

}

上面的代码中,modelBuilder.Entity().HasRequired(s => s.Address),是设置Student实体中的 StudentAddress导航类型的Address属性是必须的,.WithRequiredPrincipal(ad => ad.Student)是设置StudentAddress实体中的Student属性是必须的。

使用 EF Power Tools为上面的一对一的例子创建实体对象模型,如下:
11.翻译系列:在EF 6中配置一对零或者一对一的关系【EF 6 Code-First系列】_第2张图片

这一节,一对一的关系就讲解完了,下一节学习一对多的关系。

你可能感兴趣的:(11.翻译系列:在EF 6中配置一对零或者一对一的关系【EF 6 Code-First系列】)