Code First 约定(Conventions)

Posted springsnow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Code First 约定(Conventions)相关的知识,希望对你有一定的参考价值。

Entity Framework 简言之就是一个ORM(Object-Relational Mapper)框架.

Code First 使得你能够通过C#的类来描述一个模型,模型如何被发现/检测就是通过一些约定(Conventions)。

Conventions 就是一系列规则的集合,被用于对基于类定义的概念模型的自动配置

这些约定都被定义于 System.Data.Entity.ModelConfiguration.Conventions 命名空间下。

当然你可以使用 Data Annotations 或者 Fluent API进一步地对你的模型作出配置。

推荐的配置顺序如下:优先使用 Fluent API ,然后是, Data Annotations 和Conventions.

本文将会给出一个关于 Conventions 的初步介绍,具体详细的列表请参考 http://msdn.microsoft.com/en-us/library/system.data.entity.modelconfiguration.conventions(v=vs.103).aspx

一、类型发现约定 Type Discovery

  当我们使用 Entity Framework 进行开发的时候,通常是以构建一些定义概念模型的类开始,除此之外,我们还需要让 DbContext 知道哪些类型需要包含在此模型中。

为此,我们定义了一个从DbContext派生的上下文类,并公开了要成为模型一部分的类型的DbSet属性。这样 Code First 将包含这些类型以及这些类型的引用类型(即便引用类型定义于不同的程序集中)

  如果类型位于继承体系中,也只需为基类(base class)定义 DbSet 属性,那么位于同一程序集中的派生类型也将被自动包含与其中。

  下面的例子中,在类 SchoolEntities 中只定义了一个 DbSet 属性 Departments ,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 属性(Attribute)或者 DbModelBuilder.Ignore fluent API.

modelBuilder.Ignore<Department>();

二、主键约定 Primary Key Convention

  如果类中的属性(Property)名称为 ID (不区分大小写)或 ClassNameID(类名 + ID),Code First 则推断这个属性为主键。如果主键属性的类型为数字型或 GUID 则会被当成标识列(Identity Column

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

    . . .  

}

三、关系(外键/导航属性)约定 Relationship(Foreign Key/Navigation Properties) Convention

  在 Entity Framework 中,导航属性(Navigation Properties)提供了一种对两个实体类型之间关系的驱动,每一个对象都能拥有它所参与的每一个关系的导航属性(每一个对象的每一个关系都能有一个导航属性),导航属性提供在两端来驱动或操作这个关系,也可以返回任何一方的引用对象(对象间的关系是 1:1 或者 1:0 )或 对象的集合(对象间的关系为 1:* *:*), Code First 根据定义于类型上的导航属性能够推断这种关系。

  除了导航属性外,推荐的方式是再包含外键属性(Foreign Key)。Code First 能够推断如下的命名属性为外键(外键属性命名的默认约定):

  • <导航属性名><主体主键属性名>;
  • <主体类名><主键属性名>;
  • <主体主键属性名>

  优先顺序为从上到下(多个满足匹配/约定的时候)。外键属性命名约定也是大小写不敏感的。(PS: 个人觉得把 Principal 译为主体,Dependent Entity 译为从属实体较为稳妥,分别对应主从关系)

  当外键属性被检测到,Code First 将会根据外键的可空性来推断关系的具体形式:如果属性是可空的,那么关系将被注册为可选的;否则则被认为是必须的。

  如果从属实体上的外键是不可为空的,Code First 将会在关系上设置级联删除,反之,则不会级联删除,并且当主体被删除的时候,外键将会被置为 NULL

  多说一句:以上所说的关系多重性(multiplicity)和级联删除可以被 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; }
}

四、复杂类型约定 Complex Types Conventions

  如果 Code First 无法从类定义中推断出主键,也没有通过 Data AnnotationsFluent API 注册的主键,则此类型自动注册为 Complex Types.

Complex Types 此外还要求类型中不能含有对其它实体类型的引用,并且其它类型中也不能含有对本类型引用的属性集合。

一个 Complex Type 示例如下所示,以下类定义 Code First 将推断,详细信息是复杂类型,因为它没有主键。

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

五、移除约定 Removing Conventions

  可以移除定义于命名空间 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>();
    }
}

说明:本文是在学习 Entity Framework Code First Conventions 的随笔记录,对原文做了一个意译以更好地为自己所用。原文请参考 http://msdn.microsoft.com/en-us/data/jj679962 (推荐阅读)

以上是关于Code First 约定(Conventions)的主要内容,如果未能解决你的问题,请参考以下文章

转:Entity Framework 5.0 Code First全面学习

EF Code-First 学习之旅 Code First Conventions

小白学习之Code First

Entity Framework Code First Custom Conventions

Entity Framework Code First Data Annotations

Entity Framework Code First Fluent API - 配置属性/类型