【译】第26节---配置一对多关系

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

本节,我们将学习如何在Code First中配置两个实体之间的一对多关系。

举一个Student和Standard(年级)实体的例子,其中,一个Standard可以包括许多Student。 所以Student与Standard实体之间的关系将是一对多的。

使用DataAnnotation配置一对多关系

来看下面Student与Standard实体:

public class Student
{
    public Student() { }

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

    public virtual Standard Standard { get; set; }
}

public class Standard
{
    public Standard()
    {
        Students = new List<Student>();
    }
    public int StandardId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

上述示例中,Student实体包括导航属性Standard,Standard实体包括Student的集合属性。 这是形成一对多关系的默认约定。

如果实体类遵循此约定,则我们不需要使用DataAnnotations或Fluent API配置一对多关系。

EF Code First将通过在Student表中添加Standard_StandardId列来创建一对多关系,如下所示:

实体包括外键Id属性:

建议在实体类中包含外键属性。 例如,Student实体包含自动变为foreignkey属性的StandardId属性,因为它符合外键<Type Name> Id的约定。

如果foreignkey属性名称不符合约定,例如,Student实体对于Standard实体使用了不同名称的外键(不是StandardId),那么我们需要在属性上应用ForeignKey属性。

例如,以下Student实体包括StandardRefId属性:

public class Student
{
    public Student() { }

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

        public int StdandardRefId { get; set; }

    [ForeignKey("StandardRefId")]
    public virtual Standard Standard { get; set; }
}

public class Standard
{
    public Standard()
    {
        Students = new List<Student>();
    }
    public int StandardId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

上述示例中,ForeignKey属性应用于Standard导航属性以指定Standard属性的foreignkey属性名称。所以EF将创建一个StandardRefId列作为FK,如下所示:

使用Fluent API配置一对多关系

这里,我们将学习使用Fluent API的Student和Standard实体之间的一对多关系。

让我们为以下Student和Standard实体配置一对多关系:

public class Student
{
    public Student(){ }

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

    public int StandardId { get; set; }

    public virtual Standard Standard { get; set; }
}

public class Standard
{
    public Standard()
    {
        StudentsList = new List<Student>();
    }
    public int StandardId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

你可以按照一下代码进行配置:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
        //one-to-many
        modelBuilder.Entity<Student>()
                    .HasRequired<Standard>(s => s.Standard) // Student entity requires Standard
                    .WithMany(s => s.Students); // Standard entity includes many Students entities

}

假设Student和Standard实体类没有遵循外键的Code First约定:

public class Student
{
    public Student(){ }

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

    //StdId is not following code first conventions name
    public int StdId { get; set; }

    public virtual Standard Standard { get; set; }
}

public class Standard
{
    public Standard()
    {
        StudentsList = new List<Student>();
    }
    public int StandardId { get; set; }
    public string Description { get; set; }

    public virtual ICollection<Student> Students { get; set; }
}

所以,你可以通过Fluent API使用Student实体类配置一对多关系,如下所示:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
        //one-to-many
        modelBuilder.Entity<Student>()
                    .HasRequired<Standard>(s => s.Standard)
                    .WithMany(s => s.Students)
                    .HasForeignKey(s => s.StdId);

}

可以看到,modelBuilder.Entity <Student>().HasRequired <Standard>(s => s.Standard)指定Student实体需要NotNull标准导航属性。

.WithMany(s => s.Students).HasForeignKey(s => s.StdId)指定Standard实体可以包括多个Student在学生集合属性中,外键是StdId。

另一种可行的方式:我们也可以从Standard实体开始:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
        //configure one-to-many
        modelBuilder.Entity<Standard>()
                    .HasMany<Student>(s => s.Students) //Standard has many Students
                    .WithRequired(s => s.Standard)  //Student require one Standard
                    .HasForeignKey(s => s.StdId);//Student includes specified foreignkey property name for Standard
}

上面的代码将创建以下数据库:

注意StdId不为空列。 所以每次添加或更新Student时,都必须为Student实体指定Standard。

一对多关系中的可空外键:

使用HasOptional方法代替HasRequired方法使外键列为空。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
        //one-to-many
        modelBuilder.Entity<Student>()
                    .HasOptional<Standard>(s => s.Standard)
                    .WithMany(s => s.Students)
                    .HasForeignKey(s => s.StdId);

}

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

时间: 2024-10-25 13:42:20

【译】第26节---配置一对多关系的相关文章

Configure One-to-Many(配置一对多关系)【Code-First系列】

现在,我们将学习怎么配置一对多的关系. Visit Entity Relationship section to understand how EF manages one-to-one, one-to-many, and many-to-many relationships between the entities. Note: You do not need to configure for one-to-many relationships either using DataAnnotat

Jpa配置一对多关系

在网上查了很多关于jpa的一对多表关联的操作,踩了很多坑,今天终于解决了 下面上一下我自己的代码,记录一下 老师和学生(一对多关系) 首先搭建环境,添加依赖包 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSche

Configure Many-to-Many(配置多对多关系)【Code-First系列】

现在学习EF Code-First多对多的配置. 这里我们举例:学生和班级实体,一个学生可以选修多个课程,多个学生也可以选修同一个课程. 一.使用数据注解特性,配置多对多的关系 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace EF7 { public class Student { public

使用annotation配置hibernate(2):一对多关系配置

数据表结构 单向一对多 Student.java 1 @Entity 2 @Table(name = "student") 3 public class Student { 4 @Id 5 @Column(name = "id") 6 @GenericGenerator(name = "generator",strategy = "native") 7 @GeneratedValue(generator = "gen

MyBatis_4_一对多关系配置

---5-1 一对多关系配置1-------------------------------------------------------------- message package com.imooc.bean; /** * 与消息表对应的实体类 */ public class Message { /** * 主键 */ private String id; /** * 指令名称 */ private String command; /** * 描述 */ private String d

MyBatis学习笔记(五)一对多关系

有了之前的student表,address表后,再加上一张表,grade年级表,一个年级对应多个学生,在查询grade表的时候,一并查询学生表. 一条grade数据对就多条学生数据,一对多关系. 一.首先完成从grade----> student的单向联结. 1.建表mybatis_grade. [html] view plain copy package com.skymr.mybatis.model; import java.util.List; public class Grade { p

[NHibernate]一对多关系(关联查询)

目录 写在前面 文档与系列文章 一对多查询 总结 写在前面 上篇文章介绍了nhibernate的一对多关系如何配置,以及级联删除,级联添加数据的内容.这篇文章我们将学习nhibernate中的一对多关系的关联查询.前面文章中也介绍的nhibernate的查询:HQL,条件查询,原生SQL查询. 文档与系列文章 [Nhibernate]体系结构 [NHibernate]ISessionFactory配置 [NHibernate]持久化类(Persistent Classes) [NHibernat

hibernate学习(5)——一对多关系表达

一对多实现 1. 实现类 package com.alice.hibernate02.vo; import java.util.HashSet; import java.util.Set; public class Customer { private Integer id; private String name; // 一对多:一个客户(当前客户) 拥有 [多个订单] // * 需要容器存放多个值,一般建议Set (不重复.无序) // * 参考集合:List.Map.Array等 // *

[Fluent NHibernate]一对多关系处理

目录 写在前面 系列文章 一对多关系 总结 写在前面 上篇文章简单介绍了,Fluent Nhibernate使用代码的方式生成Nhibernate的配置文件,以及如何生成持久化类的映射文件.通过上篇的学习你会发现,Fluent Nhibernate仍然需要引用Nhibernate的两个程序集(Nhibernate.dll和Iesi.Collections.dll),所以与Nhibernate最大的区别就在生成配置文件的方式上面,这里关于Nhibernate的特性方面就不再多赘述,可以参考Nhib