上篇博文說過當我們定義的類不能遵循約定(Conventions)的時候,Code First 提供了兩種方式來配置你的類:DataAnnotations 和 Fluent API, 本文將關注 Fluent API.
一般來說我們訪問 Fluent API 是通過重寫繼承自 DbContext 的類中方法 OnModelCreating. 為了便於例示,我們先創建一個繼承自 DbContext 的類,以及其它的一些類以便使用

public class SchoolEntities : DbContext { public DbSet<Course> Courses { get; set; } public DbSet<Department> Departments { get; set; } public DbSet<Instructor> Instructors { get; set; } public DbSet<OfficeAssignment> OfficeAssignments { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { // Configure Code First to ignore PluralizingTableName convention // If you keep this convention then the generated tables will have pluralized names. modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); } } public class Department { public Department() { this.Courses = new HashSet<Course>(); } // Primary key public int DepartmentID { get; set; } public string Name { get; set; } public decimal Budget { get; set; } public System.DateTime StartDate { get; set; } public int? Administrator { get; set; } // Navigation property public virtual ICollection<Course> Courses { get; private set; } } public class Course { public Course() { this.Instructors = new HashSet<Instructor>(); } // 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 virtual ICollection<Instructor> Instructors { get; private set; } } public partial class OnlineCourse : Course { public string URL { get; set; } } 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; } } public class Instructor { public Instructor() { this.Courses = new List<Course>(); } // Primary key public int InstructorID { get; set; } public string LastName { get; set; } public string FirstName { get; set; } public System.DateTime HireDate { get; set; } // Navigation properties public virtual ICollection<Course> Courses { get; private set; } } public class OfficeAssignment { // Specifying InstructorID as a primary [Key()] public Int32 InstructorID { get; set; } public string Location { get; set; } // When the Entity Framework sees Timestamp attribute // it configures ConcurrencyCheck and DatabaseGeneratedPattern=Computed. [Timestamp] public Byte[] Timestamp { get; set; } // Navigation property public virtual Instructor Instructor { get; set; } }
Model-Wide Setting
HasDefaultSchema() - Default Schema(EF6 onwards)
從 EF6 開始可以使用 DbModelBuilder 中的方法 HasDefaultSchema 來指定所有的表/存儲過程/視圖等屬於哪一個 database schema
modelBuilder.HasDefaultSchema("sales");
PS 1: 在 EF 之前的版本中默認的 schema 是被 hard-coded 成 "dbo", 唯一改變它的方式是使用 ToTable API
PS 2: 解釋一下 database schema, 它就是對諸如表、視圖、存儲過程等的一種邏輯分組的方式(可以想象成對象的集合),你可以把一個 schema 賦予用戶以便他能夠訪問所有經過授權的對象。Schemas 在數據庫中可以被創建並被更新,用戶也可以被授權訪問它,一個 schema 可以被定義成任意用戶擁有,並且 schema 的所有權是可以被轉移的。我們可以看一下數據庫中的 schema
Custom Conventions(EF6 onwards)
約定配置請參考文章 http://www.cnblogs.com/panchunting/p/entity-framework-code-first-custom-conventions.html
Property Mapping 屬性映射
HasKey() - Primary Key
指定屬性為主鍵
// Primary Key modelBuilder.Entity<OfficeAssignment>() .HasKey(t => t.InstructorID);
也可以指定多個屬性為聯合主鍵
// Composite Primary Key modelBuilder.Entity<Department>() .HasKey(t => new { t.DepartmentID, t.Name });
HasDatabaseGeneratedOption()
為數字型主鍵取消數據庫生成
// Switching off Identity for Numeric Primary Keys modelBuilder.Entity<Department>() .Property(t => t.DepartmentID) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
HasMaxLength() - Specifying the Length on a Property
指定屬性長度
// Specifying the Maximum Length on a Property modelBuilder.Entity<Department>() .Property(t => t.Name) .HasMaxLength(50);
IsRequired() - Configuring the Property to be Required
必填字段
// Configuring the Property to be Required modelBuilder.Entity<Department>() .Property(t => t.Name) .IsRequired();
Ignore() - Specifying Not to Map a CLR Property to a Column in the Database
忽略
// Specifying Not to Map a CLR Property to a Column in the Database modelBuilder.Entity<Department>() .Ignore(t => t.Budget);
HasColumnName() - Mapping a CLR Property to a Specific Column in the Database
指定列名
// Mapping a CLR Property to a Specific Column in the Database modelBuilder.Entity<Department>() .Property(t => t.Name) .HasColumnName("DepartmentName");
MapKey - Renaming a Foreign Key That Is Not Defined in the Model
指定外鍵名
// Renaming a Foreign Key That Is Not Defined in the Model modelBuilder.Entity<Course>() .HasRequired(c => c.Department) .WithMany(t => t.Courses) .Map(m => m.MapKey("ChangedDepartmentID"));
HasColumnType() - Configuring the Data Type of a Database Column
指定列類型
// Configuring the Data Type of a Database Column modelBuilder.Entity<Department>() .Property(p => p.Name) .HasColumnType("varchar");
Configuring Properties on a Complex Type
在復雜類型(Complex Type)上有兩種方式來配置 scalar properties
在 ComplexTypeConfiguration 上調用 Property
// Call Property on ComplexTypeConfiguration modelBuilder.ComplexType<Details>() .Property(t => t.Location) .HasMaxLength(20);
也可以使用點標記法來訪問復雜類型上的屬性
// Use the dot notation to access a property of a complex type modelBuilder.Entity<OnsiteCourse>() .Property(t => t.Details.Location) .HasMaxLength(20);
IsConcurrencyToken() - Configuring a Property to Be Used as an Optimistic Concurrency Token
設置樂觀並發標記
// Configuring a Property to Be Used as an Optimistic Concurrency Token modelBuilder.Entity<OfficeAssignment>() .Property(t => t.Timestamp) .IsConcurrencyToken();
IsRowVersion() - Configuring a Property to Be Used as an Optimistic Concurrency Token
設置樂觀並發標記,效果同上
// Configuring a Property to Be Used as an Optimistic Concurrency Token modelBuilder.Entity<OfficeAssignment>() .Property(t => t.Timestamp) .IsRowVersion();
Type Mapping類型映射
ComplexType() - Specifying That a Class Is a Complex Type
指定復雜類型
// Specifying That a Class Is a Complex Type modelBuilder.ComplexType<Details>();
Ingore() - Specifying Not to Map a CLR Entity Type to a Table in the Database
忽略實體類型
// Specifying Not to Map a CLR Entity Type to a Table in the Database modelBuilder.Ignore<OnlineCourse>();
ToTable() - Mapping an Entity Type to a Specific Table in the Database
映射表名
// Mapping an Entity Type to a Specific Table in the Database modelBuilder.Entity<Department>() .ToTable("t_Department");
也可以同時指定 schema
// Mapping an Entity Type to a Specific Table in the Database modelBuilder.Entity<Department>() .ToTable("t_ Department", "school");
Mapping the Table-Per-Hierarchy (TPH) Inheritance
映射 TPH
// Mapping the Table-Per-Hierarchy (TPH) Inheritance modelBuilder.Entity<Course>() .Map<Course>(m => m.Requires("Type").HasValue("Course")) .Map<OnsiteCourse>(m => m.Requires("Type").HasValue("OnsiteCourse"));
Mapping the Table-Per-Type (TPT) Inheritance
映射 TPT
// Mapping the Table-Per-Type (TPT) Inheritance modelBuilder.Entity<Course>().ToTable("Course"); modelBuilder.Entity<OnsiteCourse>().ToTable("OnsiteCourse");
Mapping the Table-Per-Concrete Class (TPC) Inheritance
映射 TPC
// Mapping the Table-Per-Concrete Class (TPC) Inheritance modelBuilder.Entity<Course>() .Property(c => c.CourseID) .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); modelBuilder.Entity<OnsiteCourse>() .Map(m => { m.MapInheritedProperties(); m.ToTable("OnsiteCourse"); }); modelBuilder.Entity<OnlineCourse>() .Map(m => { m.MapInheritedProperties(); m.ToTable("OnlineCourse"); });
Mapping Properties of an Entity Type to Multiple Tables in the Database (Entity Splitting)
映射實體中屬性到多張表中
- 實體 Department 屬性 DepartmentID, Name 映射到表 Department;
- 同時屬性 DepartmentID, Administrator, StartDate, Budget 映射到表 DepartmentDetails
// Mapping Properties of an Entity Type to Multiple Tables in the Database (Entity Splitting) modelBuilder.Entity<Department>() .Map(m => { m.Properties(t => new { t.DepartmentID, t.Name }); m.ToTable("Department"); }) .Map(m => { m.Properties(t => new { t.DepartmentID, t.Administrator, t.StartDate, t.Budget }); m.ToTable("DepartmentDetails"); });
Mapping Multiple Entity Types to One Table in the Database (Table Splitting)
映射多個實體到一張表:實體 Instructor 和 OfficeAssignment 映射到同一張表 Instructor
// Mapping Multiple Entity Types to One Table in the Database (Table Splitting) modelBuilder.Entity<OfficeAssignment>() .HasKey(t => t.InstructorID); modelBuilder.Entity<Instructor>() .HasRequired(t => t.OfficeAssignment) .WithRequiredPrincipal(t => t.Instructor); modelBuilder.Entity<Instructor>().ToTable("Instructor"); modelBuilder.Entity<OfficeAssignment>().ToTable("Instructor");
Mapping an Entity Type to Insert/Update/Delete Stored Procedures (EF6 onwards)
映射實體到增、改、更、刪 存儲過程,詳情請參考文章 http://www.cnblogs.com/panchunting/p/entity-framework-code-first-insert-update-delete-stored-procedures
PS: 關於TPH, TPT, TPC 以后有時間專門寫一篇文章介紹
原文參考:http://msdn.microsoft.com/en-us/data/jj591617