Code First 公約

Code First 讓你能透過 C# 或 Visual Basic 的 .NET 類別來描述模型。 模型的基本形狀是透過慣例來偵測的。 慣例是一組規則,用於在使用 Code First 時,根據類別定義自動配置概念模型。 這些慣例定義於 System.Data.Entity.ModelConfiguration.Conventions 命名空間中。

你可以透過資料註解或流暢 API 進一步配置模型。 優先配置是透過流暢 API 進行,接著是資料註解,最後是慣例。 欲了解更多資訊,請參閱 資料註解Fluent API - 關係Fluent API - 類型與屬性 ,以及 Fluent API with VB.NET

Code First 的詳細慣例清單可在 API 文件中找到。 本主題概述了 Code First 所使用的慣例。

型態發現

使用 Code First 開發時,通常會先撰寫 .NET Framework 類別來定義你的概念(領域)模型。 除了定義類別外,你還需要讓 DbContext 知道你想包含哪些類型。 為此,你需要定義一個上下文類別,並公開你想成為模型一部分的 DbSet 屬性,該類別源自 DbContext。 Code First 會包含這些類型,並且會拉入任何被引用的類型,即使這些參考類型是在不同的組合語言中定義的。

如果你的型別參與繼承階層,只要為基底類別定義一個 DbSet 屬性就足夠了,若衍生型別與基底類別在同一組語言中,它們會自動被包含。

在以下範例中,SchoolEntities 類別(部門)上僅定義了一個 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>();

主鍵慣例

Code First 推斷,若類別上的屬性名為「ID」(不區分大小寫),或是類別名稱後接「ID」,則該屬性為主鍵。 若主鍵屬性的類型為數字或 GUID,則會設定為身份欄位。

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

    . . .  

}

關係慣例

在 Entity Framework 中,導覽屬性提供一種方式來巡覽兩個實體類型之間的關聯性。 每個物件都可以為其所參與的每個關係擁有一個導航屬性。 導航屬性允許你雙向導航和管理關係,若重數為一或零或一,則回傳參考物件,若多則回傳一個集合。 Code First 會根據你型別中定義的導航屬性推斷關係。

除了導航屬性外,我們建議你在代表相依物件的類型中加入外鍵屬性。 任何與主鍵屬性資料型別相同且名稱遵循以下任一格式的屬性,代表該關係的外鍵:『<導航屬性名稱><、主鍵屬性名稱>」、「<主類別名稱><、主鍵屬性名稱>』或『<主主要鍵屬性名稱>』。 若發現多個匹配,則依上述順序排序。 外鍵偵測對大小寫不敏感。 當偵測到外金鑰屬性時,Code First 會根據外鍵的可空性推斷該關係的多重性。 若該性質為可空性,則該關係被登記為可選;否則關係將依規定登記。

如果相依實體上的外鍵不可空,Code First 則針對該關係設定級聯刪除。 若依賴實體的外鍵可為空,Code First 不會對該關係設定級聯刪除,當主體被刪除時,外鍵將設為空。 慣例偵測到的多重性與連鎖刪除行為可透過 fluent API 覆蓋。

以下範例中使用導航屬性與外鍵來定義系所類別與課程類別之間的關係。

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 類別包含 Author 和 Reviewer 的導航屬性),你需要透過 Data Annotations 或 Fluent API 手動設定這些關係。 欲了解更多資訊,請參閱資料註解 - 關係流暢 API - 關聯。

複合資料型別約定

當 Code First 發現一個類別定義無法推斷主鍵,且資料註解或流暢 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 開始支援自訂慣例。 欲了解更多資訊,請參閱 「自訂程式碼優先慣例」。