通过


代码优先约定

Code First 使你能够使用 C# 或 Visual Basic .NET 类来描述模型。 使用标准检测模型的基本形状。 约定是一组规则,用于在使用 Code First 时基于类定义自动配置概念模型。 约定在 System.Data.Entity.ModelConfiguration.Conventions 命名空间中定义。

可以使用数据注释或 Fluent API 进一步配置模型。 优先通过 fluent API 进行配置,然后是数据注释,最后是约定。 有关详细信息,请参阅数据注释Fluent API - 关系Fluent API - 类型和属性以及具有 VB.NET 的 Fluent API

API 文档中提供了 Code First 约定的详细列表。 本主题概述了 Code First 使用的约定。

类型识别

使用 Code First 开发时,通常首先编写定义概念(域)模型的 .NET Framework 类。 除了定义类之外,还需要让 DbContext 知道要在模型中包含的类型。 为此,请定义派生自 DbContext 的上下文类,并公开要作为模型一部分的类型的 DbSet 属性。 Code First 将包括这些类型,并且还将引入任何引用的类型,即使这些引用的类型定义在不同的程序集中也是如此。

如果类型参与继承层次结构,则足以定义基类的 DbSet 属性,并且如果派生类型与基类位于同一程序集中,则派生类型将自动包含。

在以下示例中,SchoolEntities 类(Departments)上只定义了一个 DbSet 属性。 Code First 使用此属性来查找并获取所有引用的类型。

public class SchoolEntities : DbContext
{
    public DbSet<Department> Departments { get; set; }
}

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
}

public partial class OnlineCourse : Course
{
    public string URL { get; set; }
}

public partial class OnsiteCourse : Course
{
    public string Location { get; set; }
    public string Days { get; set; }
    public System.DateTime Time { get; set; }
}

如果要从模型中排除类型,请使用 NotMapped 属性或 DbModelBuilder.Ignore fluent API。

modelBuilder.Ignore<Department>();

主键约定

如果类上的属性名为“ID”(不区分大小写),或者类名后跟“ID”,则 Code First 推断属性是主键。 如果主键属性的类型为数值或 GUID,则会将其配置为标识列。

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }

    . . .  

}

关系约定

在 Entity Framework 中,导航属性提供了一种导航两种实体类型之间的关系的方法。 每个对象都可以为其参与的每个关系都有一个导航属性。 导航属性允许你以两个方向导航和管理关系,返回引用对象(如果多重性为一个或零或一个)或集合(如果多重性很多)。 Code First 根据类型定义的导航属性推断关系。

除了导航属性,建议在表示依赖对象的类型上包括外键属性。 任何数据类型与主体主键属性相同的属性,并且采用以下格式之一的名称表示关系的外键:“<导航属性名称><主体主键属性名称>”、“<主体类名称><主键属性名称>”,或“<主体主键属性名称>”。 如果找到多个匹配项,则按上面列出的顺序给出优先级。 外键检测不区分大小写。 检测到外键属性时,Code First 会根据外键的可为 null 性推断关系的多重性。 如果该属性可为 null,则关系注册为可选;否则,关系会根据需要注册。

如果依赖实体上的外键不可为 null,则 Code First 对关系设置级联删除。 如果依赖实体上的外键可为 null,则 Code First 不会对关系设置级联删除,当主体被删除时,外键将设置为 null。 可以使用“fluent API”覆盖约定检测到的多重性和级联删除行为。

在下面的示例中,导航属性和外键用于定义 Department 和 Course 类之间的关系。

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
}

注释

如果同一类型之间存在多个关系(例如,假设你定义了 PersonBook 类,其中 Person 类包含 ReviewedBooksAuthoredBooks 导航属性,而 Book 类包含 AuthorReviewer 导航属性),则需要使用数据注释或 Fluent API 手动配置关系。 有关详细信息,请参阅 数据注释 - 关系Fluent API - 关系

复杂类型约定

如果 Code First 发现无法推断主键的类定义,并且没有通过数据注释或 fluent API 注册主键,则类型会自动注册为复杂类型。 复杂类型检测还要求该类型没有引用实体类型的属性,并且不会从另一类型的集合属性引用。 给定以下类定义 Code First 会推断 Details 是复杂类型,因为它没有主键。

public partial class OnsiteCourse : Course
{
    public OnsiteCourse()
    {
        Details = new Details();
    }

    public Details Details { get; set; }
}

public class Details
{
    public System.DateTime Time { get; set; }
    public string Location { get; set; }
    public string Days { get; set; }
}

连接字符串约定

若要了解 DbContext 用于发现连接的约定,请参阅 连接和模型

删除约定

可以删除 System.Data.Entity.ModelConfiguration.Conventions 命名空间中定义的任何约定。 以下示例删除 PluralizingTableNameConvention

public class SchoolEntities : DbContext
{
     . . .

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Configure Code First to ignore PluralizingTableName convention
        // If you keep this convention, the generated tables  
        // will have pluralized names.
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

自定义约定

EF6 及更高版本支持自定义约定。 有关详细信息,请参阅 自定义代码优先约定