Entity Framework - 关系 / 映射 / 外键

2014-03-01 23:00
2018-10-04 23:41

Brief - 关系映射

  • 在关系数据库中,表之间的 关系/关联 是通过外键定义的。
  • 外键 是用于在两个表的数据之间建立并强制链接的一列或列组合。
  • 有 3 种关系类型: 一对一、一对多、多对多。
  • 在一对一关系中,主键还用作外键,两个表都没有单独的外键列。
  • 在一对多关系中,外键是在表示关系多端的表上定义的。
  • 多对多关系涉及定义第三个表 (也称为接合或联接表),主键由来自两个相关表的外键组成。


  1. Entity Framework Code First 关系映射约定 - Tony Praise
  2. Entity Framework 自动生成数据库外键 "表名_外键" 的解决方案
  3. Entity Framework 7 - 演示 实体类 基类
  4. Entity Framework 4.1 - Code First 指定外键名称

POCO 中的导航属性如何映射外键


Tony copy from http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-basic-crud-functionality-with-the-entity-framework-in-asp-net-mvc-application at 2013-11-19 (2015-11-10 该页面有 Bing Translator 小工具可将该页面译为汉语).

2015-11-10 Tony Remark: StudentCourse 是 "多对多" 的关系,Enrollment 是 "关系表"。


using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace ContosoUniversity.Models

    public enum Grade
        A, B, C, D, F

    public class Student
        public int ID { get; set; }
        public string LastName { get; set; }
        public string FirstMidName { get; set; }
        public DateTime EnrollmentDate { get; set; }
        public virtual ICollection<Enrollment> Enrollments { get; set; }

    public class Enrollment
        public int EnrollmentID { get; set; }
        public int CourseID { get; set; }
        public int StudentID { get; set; }
        public Grade? Grade { get; set; }
        public virtual Course Course { get; set; }
        public virtual Student Student { get; set; }

    public class Course
        public int CourseID { get; set; }
        public string Title { get; set; }
        public int Credits { get; set; }
        public virtual ICollection<Enrollment> Enrollments { get; set; }


对上述 Student 类的说明

The ID property will become the primary key column of the database table that corresponds to this class. By default, the Entity Framework interprets a property that's named ID or classnameID as the primary key.

The Enrollments property is a navigation property. Navigation properties hold other entities that are related to this entity. In this case, the Enrollments property of a Student entity will hold all of the Enrollment entities that are related to that Student entity. In other words, if a given Student row in the database has two related Enrollment rows (rows that contain that student's primary key value in their StudentID foreign key column), that Student entity's Enrollments navigation property will contain those two Enrollment entities.

Navigation properties are typically defined as virtual so that they can take advantage of certain Entity Framework functionality such as lazy loading. (Lazy loading will be explained later, in the Reading Related Data tutorial later in this series.)

If a navigation property can hold multiple entities (as in many-to-many or one-to-many relationships), its type must be a list in which entries can be added, deleted, and updated, such as ICollection.

对上述 Enrollment 类的说明

The EnrollmentID property will be the primary key; this entity uses the classnameID pattern. In a later tutorial you'll see why we use ID without classname for the Student entity but classnameID in other entities; for now, the variation illustrates that you can use either pattern.

The Grade property is an enum. The question mark after the Grade type declaration indicates that the Grade property is nullable. A grade that's null is different from a zero grade — null means a grade isn't known or hasn't been assigned yet.

The StudentID property is a foreign key, and the corresponding navigation property is Student. An Enrollment entity is associated with one Student entity, so the property can only hold a single Student entity (unlike the Student.Enrollments navigation property you saw earlier, which can hold multiple Enrollment entities).

The CourseID property is a foreign key, and the corresponding navigation property is Course. An Enrollment entity is associated with one Course entity.

Entity Framework interprets a property as a foreign key property if it's named <navigation property name><primary key property name> (for example, StudentID for the Student navigation property since the Student entity's primary key is ID). Foreign key properties can also be named the same simply <primary key property name> (for example, CourseID since the Course entity's primary key is CourseID).