EntityFramework Code-First 简易教程(八)-------一对一

配置一对一(One-to-One)关系:

两个实体中,若是一个实体的一个实例与另外一个实体相关,则咱们就叫作一对一关系数据库

查看以下代码:ide

public class Student
{
    public 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; }
}

 

这里,Student类只能拥有零个或最多一个StudentAddress类,因此符合一对一关系ui

在SQL Server数据库中,一对一关系发生在当一张表的主键是另外一张表的主键或外键时,因此如上代码中,咱们要配置StudentId为主键,StudentAddressId既为主键也为外键。spa

1.使用DataAnnotations配置一对零或一对一关系:

Student类会根据Code-First默认约定将StudentId属性配置为主键,因此这里咱们就不用额外的配置它了。.net

StudentAddress类中,咱们须要配置StudentAddressId既为主键又为外键,一样的,Code-First默认约定会将StudentAddressId配置为主键,因此这里咱们仅仅须要使用[ForeignKey("Student")]特性将StudentAddressId属性配置为外键便可。翻译

代码以下:code

public class Student
{
    public 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; }
}
View Code

 

这样,Student类和StudentAddress类就配置好了一对一关系。blog

若是StudentAddressId名称改变了,好比下面代码,改为了StudentId,默认就不会建立主键了,须要手动添加上[Key]特性:ip

public class Student
{
    public Student() { }

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

    public virtual StudentAddress Address { get; set; }

}
     
public class StudentAddress 
{
    [Key, ForeignKey("Student")]
    public int StudentId { 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; }
}
View Code

这样,StudentAddress类中的StudentId就被配置为既是主键,又是外键。ci

注意: 虽然Student类中包含StudentAddress类属性,StudentAddress类中也包含Student类属性,但Student类的StudentAddress类属性能够为空,而StudentAddress类的Student类属性不能为空!若是保存一个Student类属性为空的StudentAddress类,会抛出异常。

 

 

2.使用Fluent API配置一对零或一对一关系:

下面咱们将不使用任何DataAnnotations特性(虽然它们能够一块儿使用)仅仅使用Fluent API来配置一对一关系。

当Student类的命名和StudentAddress类的命名遵循默认约定的时候:

既然默认约定会自动为Student和StudentAddress建立主键,因此这里咱们仅仅须要把StudentAddressId配置为外键

代码以下:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    
    // Configure Student & StudentAddress entity
    modelBuilder.Entity<Student>()
                .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实体的Address属性使用了HasOptional()方法,即Address属性不是必须的,可为空,又为StudentAddress类的Student属性使用了WithRequired()方法,即Student属性为必填,不能为空,若是存储StudentAddress实体的时候发现Student属性为空,则会抛出异常。

这样配置之后,StudentAddressId就已是外键了。

当StudentAddress类的命名不遵循默认约定的时候:

以下代码,咱们想要StudentAddress类的StudentId属性成为主外键

public class Student
{
    public Student() { }

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

    public virtual StudentAddress Address { get; set; }

}
     
public class StudentAddress 
{
    public int StudentId { 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; }
}

 

Fluent API配置以下:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    // Configure StudentId as PK for StudentAddress
    modelBuilder.Entity<StudentAddress>()
        .HasKey(e => e.StudentId);
        
    // Configure StudentId as FK for StudentAddress
    modelBuilder.Entity<Student>()
                .HasOptional(s => s.Address) 
                .WithRequired(ad => ad.Student); 

}

 

 

3.使用Fluent API配置一对一关系:

说白了,所谓的一对一关系,便是两个实体类中做为主外键的类属性都不能为空。

注意:一对一关系在SQL Server中并非必须,一般使用一对零或一对一。

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

}

在上面的代码中, modelBuilder.Entity<Student>().HasRequired(s => s.Address)使得Student类的Address属性为必须,WithRequiredPrincipal(ad => ad.Student) 方法使的StudentAddress类的Student属性为必须。

注意:这里主要的实体类是Student,依赖的实体类是StudentAddress。

DataAnnotations and Fluent API都会建立以下的一对零或一对一关系的数据库:

one-to-one relationship in code first

咱们能够检查Student表和StudentAddress表之间的关系:

one-to-one relationship in code first

图表关系以下

one-to-one relationship in code first

 

 

 

 

 啊啊啊啊啊,虽然最近忙成狗,可是说好的翻译,必定会坚持下去的!!!

相关文章
相关标签/搜索