zoukankan      html  css  js  c++  java
  • 【译】第25节---配置一对一关系

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

    本节,我们将配置两个实体之间的一对零或者一对一关系。例如, Entity1可以与零个或仅一个Entity2实例相关联。

    举个例子,来看以下的Student和StudentAddress实体。

    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实体配置为一对零或一对一关系,学生可以拥有零个或最多一个StudentAddress。

    你可能知道,当一个表的主键在关系数据库(如SQL Server)中的另一个表中变为PK&FK时,会发生一对零或一对一关系。

    所以,我们需要配置上面的实体,使得EF在DB中创建Student和StudentAddresses表。其中,将StudentID在Student表中作为PK,StudentAddressId在StudentAddress表中作为PK和FK。

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

    这里,我们将在Student和StudentAddress实体上应用DataAnnotations属性来建立一对一的关系。

    >>当Student和StudentAddress实体遵循约定:

    学生实体遵循默认的Code-First约定,因为它包含将是key属性的StudentId属性。 因此,我们不需要应用任何属性,因为EF将创建Student表,并将StudentId作为数据库中的主键。

    对于StudentAddress实体,我们需要将StudentAddressId配置为PK&FK。 StudentAddressId属性遵循主键的默认约定。 所以我们不需要为PK应用任何属性。而我们还需要使它成为一个指向StudentId的外键。 所以,在StudentAddressId属性中应用[ForeignKey(“Student”)],使之成为Student实体的外键。如下所示:

    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; }
    }

    因此,Student和StudentAddress实体具有一对零或一对一的关系。

    >>当StudentAddress实体没有遵循约定:

    如果StudentAddress实体不符合PK的约定,即Id属性的不是你想要的,那么你还需要为它配置PK。 看下面的StudentAddress实体,它的属性名称为StudentId而不是StudentAddressId。

    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; }
    }

    上面的例子中,我们需要将StudentId属性配置为Key以及ForeignKey。 这将使StudentAddress实体中的StudentId属性成为PK和FK。

    注意:Student包括StudentAddress导航属性,StudentAddress包括学生导航属性。

    使用一对零或一对一关系,没有StudentAddress实体时,可以保存Student实体。

    但没有Student实体时,StudentAddress实体无法保存。如果你试着保存没有Student实体的StudentAddress实体,EF将抛出异常。

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

    这里,我们将使用Fluent API配置Student和StudentAddress实体。 注意,我们不会在Student和StudentAddress实体中应用任何DataAnnotations属性,因为我们将使用Fluent API进行配置。

    >>当Student和StudentAddress实体遵循约定:

    Student和StudentAddress实体遵循PrimaryKey的默认代码优先约定。 所以,我们不需要配置它们来定义它们的PrimaryKeys。 我们只需要配置StudentAddress实体,将StudentAddressId设置为ForeignKey。

    以下示例使用Fluent API在Student和StudentAddress之间设置一对零或一对一关系:

    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实体使用HasOptional()方法进行配置,该方法指示Student实体中的StudentAddress导航属性是可选的(保存Student实体时不需要)。

    然后,WithRequired()方法配置StudentAddress实体,使StudentAddress的Student导航属性为必需的(保存StudentAddress实体时需要,当StudentAddress实体保存时不包含Student导航属性,它将抛出异常)。 这也将使StudentAddressId为ForeignKey。

    因此,你可以在两个实体之间配置一对零或者一对一的关系,其中,可以保存Student实体时而不将StudentAddress对象附加到该实体,但是无法保存StudentAddress实体而不附加Student实体的对象。 这使得一端实体为必需的。

    >>当StudentAddress实体没有遵循约定:

    现在,我们举一个StudentAddress实体的例子,它不遵循主键约定,即具有与<type name> Id不同的Id属性名称。 看以下Student和StudentAddress实体:

    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; }
    }

    所以现在,我们需要配置StudentId属性为StudentAddress实体的主键和外键,如下所示:

    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.StudentId); 
    
    }

    使用Fluent API配置一对一关系

    我们可以使用Fluent API配置实体之间的一对一关系,其中两端都是必需的,这意味着保存的时候,Student实体对象必须包含StudentAddress实体对象,并且StudentAddress实体必须包含Student实体对象。

    注意:在MS SQL Server中技术上无法实现一对一的关系。 它一直是一到零或一对一。 EF在实体上形成一对一的关系,而不是在不在DB中。

    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)使得StudentAddress的Address属性是必需的。

    .WithRequiredPrincipal(ad => ad.Student)使StudentAddress实体的Student属性成为必需的。

    因此,它配置两端都是必需的。

    所以现在,当你尝试保存没有Student的StudentAddress实体或者没有StudentAddress的Student时,它会抛出异常。

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

    使用DataAnnotations和Fluent API配置一对零或一对一关系的示例将创建以下数据库:

     

    你可以检查数据库中Student和StudentAddress之间的关系,如下所示:

    如果表示一个“创建的数据库的实体数据模型”,那么它将如下图所示:

    下节学习配置一对多关系。

  • 相关阅读:
    298. Binary Tree Longest Consecutive Sequence
    117. Populating Next Right Pointers in Each Node II
    116. Populating Next Right Pointers in Each Node
    163. Missing Ranges
    336. Palindrome Pairs
    727. Minimum Window Subsequence
    211. Add and Search Word
    年底购物狂欢,移动支付安全不容忽视
    成为程序员前需要做的10件事
    全球首推iOS应用防破解技术!
  • 原文地址:https://www.cnblogs.com/talentzemin/p/7274290.html
Copyright © 2011-2022 走看看