• 【译】第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之间的关系,如下所示:

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

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

  • 相关阅读:
    Sencha touch 2 入门 -------- DataView 显示服务器端JSON文件数据
    Sencha touch API
    Android Intent详解
    物流配送中商品订货数量的控制技术
    multiset基础学习,可以有重复类型的多重集合容器
    人生总会遇到浑噩期,但是需要反思
    创建Sencha touch第一个应用
    How I Turned Down $300,000 from Microsoft to go Full-Time on GitHub
    c++ list 合并操作函数实例
    电子设计与制作100例(第3版)
  • 原文地址:https://www.cnblogs.com/talentzemin/p/7274290.html
Copyright © 2020-2023  润新知