定義一個繼承自EntityTypeConfiguration<>泛型類的類來定義domain中每個類的數據庫配置,在這個自定義類的構造函數中使用我們上次提到的那些方法配置數據庫的映射。
映射實例
this.HasRequired(s => s.Company).WithMany().HasForeignKey(s => s.CompanyId); this.HasOptional(s => s.User).WithMany().HasForeignKey(s => s.UserId); this.HasRequired(s => s.User).WithOptional(s => s.WXUser); this.Property(s => s.Id).HasDatabaseGeneratedOption(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.None); this.HasRequired(p => p.User).WithOptional(p => p.UserDepartment); this.HasMany(s => s.Tags); this.HasMany(s => s.CompanyAdminUsers).WithRequired().HasForeignKey(s => s.CompanyId); HasMany(s => s.Images).WithOptional().HasForeignKey(s => s.FeedbackId); modelBuilder.Entity<Course>() .HasRequired(c => c.Department) .WithMany(t => t.Courses) .Map(m => m.MapKey("ChangedDepartmentID"));
待讀:http://www.aizhengli.com/entity-framework6-code-first-get-started/95/entity-framework-code-first--fluent-api.html
實體類關系的映射
實體類映射中,關系的映射配置在關系的兩端都可以配置。例如,用戶信息與登錄信息的 一對多 關系可以在用戶信息端配置:
HasMany(m => m.LoginLogs).WithRequired(n => n.Member);
等效於在登錄日志信息端配置:
HasRequired(m => m.Member).WithMany(n => n.LoginLogs);
但是,如果所有的關系映射都在作為主體的用戶信息端進行配置,勢必造成用戶信息端配置的臃腫與職責不明。所以,為了保持各個實體類型的職責單一,實體關系推薦在關系的非主體端進行映射。
用戶信息映射類,用戶信息是關系的主體,所有的關系都不在此映射類中進行配置
namespace GMF.Demo.Core.Data.Configurations
{
public class MemberConfiguration : EntityTypeConfiguration<Member>
{
}
}
用戶擴展信息映射類,配置用戶擴展信息與用戶信息的 0:1 關系
namespace GMF.Demo.Core.Data.Configurations
{
public class MemberExtendConfiguration : EntityTypeConfiguration<MemberExtend>
{
public MemberExtendConfiguration()
{
HasRequired(m => m.Member).WithOptional(n => n.Extend);
}
}
}
OnModelCreating配置
- ToTable - TableAttribute:配置此實體類型映射到的表名
- HasColumnName - ColumnAttribute:配置用於存儲屬性的數據庫列的名稱
- HasForeignKey - ForeignKeyAttribute:將關系配置為使用在對象模型中的外鍵屬性。如果未在對象模型中公開外鍵屬性,則使用Map方法
- Ignore - NotMappedAttribute:從模型中排隊某個屬性,使該屬性不會映射到數據庫
- HasRequired:通過此實體類型配置必需關系。除非指定此關系,否則實體類型的實例將無法保存到數據庫。數據庫中的外鍵不可為null。
- HasOptional:從此實體類型配置可選關系。實體類型的實例將能保存到數據庫,而無需指定此關系。數據庫中的外鍵可為null。
- HasMany:從此實體類型配置一對多關系。
- WithOptional:將關系配置為required:optional。(required:0…1端的1,表示必需,不可為null;optional:0…1端的0,表示可選,可為null。下同)
- WithOptionalDependent:將關系配置為optional:optional。要配置的實體類型將成為依賴對象,且包含主體的外鍵。作為關系目標的實體類型將成為關系中的主體。
- WithOptionalPrincipal:將關系配置為optional:optional。要配置的實體類型將成為關系中的主體。作為關系目標的實體類型將成為依賴對象,且包含主體的外鍵。
- WithRequired:將關系的指定端配置為必需的,且在關系的另一端有導航屬性。
- WithRequiredDependent:將關系配置為required:required。要配置的實體類型將成為依賴對象,且包含主體的外鍵。作為關系目標的實體類型將成為關系中的主體。
- WithRequiredPrincipal:將關系配置為required:required。要配置的實體類型將成為關系中的實體。作為關系目標的實體類型將成為依賴對象,且包含主體的外鍵。
- WillCascadeOnDelete:配置是否對關系啟用級聯刪除。
- Map:將關系配置為使用未在對象模型中公開的外鍵屬性。可通過指定配置操作來自定義列和表。如果指定了空的配置操作,則約定將生成列名。如果在對象模型中公開了外鍵屬性,則使用 HasForeignKey 方法。並非所有關系都支持在對象模型中公開外鍵屬性。
- MapKey:配置外鍵的列名。
- ToTable:配置外鍵列所在表的名稱和架構。
屬性映射
主要配置:主鍵、數值長度、配置為必須、不映射,外鍵等
配置主鍵:
modelBuilder.Entity<ClassA>().HasKey(t => t.ID); //配置ClassA的ID屬性為主鍵
配置聯合主鍵:
modelBuilder.Entity<ClassA>().HasKey(t => new { t.ID, t.Name }); //配置ClassA的ID和Name為主鍵
設置數據非數據庫生成:
modelBuilder.Entity<ClassA>().Property(t => t.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); //ClassA的Id屬性不用數據庫控制生成
設置字段最大長度:
modelBuilder.Entity<ClassA>().Property(t => t.Name).HasMaxLength(100); //設置ClassA類的Name屬性的最大長度為100,如果值長度100,會拋出 DbEntityValidationException異常
設置字段為必需:
modelBuilder.Entity<ClassA>().Property(t =>t.Id).IsRequired(); //設置ClassA類的Id屬性為必需
屬性不映射到數據庫:
modelBuilder.Entity<ClassA>().Ignore(t => t.A); //調過ClassA類的A屬性,讓之不映射到數據庫中
將屬性映射到數據庫中特定列名:
modelBuilder.Entity<ClassA>()
.Property(t => t.A)
.HasColumnName("A_a"); //將類ClassA的屬性A映射到數據庫中對應列名A_a
類中不指定外鍵,但在數據庫中指定外鍵名:
modelBuilder.Entity<Staff>()
.HasRequired(c => c.Department)
.WithMany(t => t.Staffs)
.Map(m => m.MapKey("DepartmentID")); //指定員工表中DepartmentID為Staff到Department的外鍵
指定屬性映射的字段為Unicode類型:
modelBuilder.Entity<ClassA>()
.Property(t => t.Name)
.IsUnicode(true);
設置屬性映射的列的類型:
modelBuilder.Entity<Department>()
.Property(p => p.Name)
.HasColumnType("varchar"); //設置列為varchar類型
設置復雜類型的屬性(何為復雜類型? 沒指定主鍵的類型):
modelBuilder.ComplexType<Details>()
.Property(t => t.Location)
.HasMaxLength(20);
modelBuilder.Entity<OnsiteCourse>()
.Property(t => t.Details.Location)
.HasMaxLength(20);
顯示設定為復雜類型:
modelBuilder.ComplexType<ClassA>();
將屬性配置為用作樂觀並發令牌:
方法1、用 ConcurrencyCheck 特性或 IsConcurrencyToken 方法
modelBuilder.Entity<OfficeAssignment>()
.Property(t => t.Timestamp)
.IsConcurrencyToken();
方法2、IsRowVersion
modelBuilder.Entity<OfficeAssignment>()
.Property(t => t.Timestamp)
.IsRowVersion();
忽略類型,不映射到數據庫中:
modelBuilder.Ignore<OnlineCourse>();
設置索引
您必須添加引用 ︰using System.Data.Entity.Infrastructure.Annotations;
基本例子
在這里是一種簡單的用法,加上 User.FirstName屬性的索引
modelBuilder .Entity<User>() .Property(t => t.FirstName) .HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute()));
實例 ︰
在這里是一個更現實的例子。它對多個屬性添加一個 唯一索引 ︰ User.FirstName和 User.LastName,與索引名稱"IX_FIrstNameLastName"
modelBuilder .Entity<User>() .Property(t => t.FirstName) .IsRequired() .HasMaxLength(60) .HasColumnAnnotation( IndexAnnotation.AnnotationName, new IndexAnnotation( new IndexAttribute("IX_FirstNameLastName", 1) { IsUnique = true })); modelBuilder .Entity<User>() .Property(t => t.LastName) .IsRequired() .HasMaxLength(60) .HasColumnAnnotation( IndexAnnotation.AnnotationName, new IndexAnnotation( new IndexAttribute("IX_FirstNameLastName", 2) { IsUnique = true }));
數據庫模型發生改變的處理
暴力處理:直接刪除掉后重新生成
namespace Portal
{
public class PortalContext : DbContext
{
static PortalContext()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<PortalContext>());
}
public DbSet<Province> Provinces { get; set; }
public DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new ProvinceMap());
modelBuilder.Configurations.Add(new CategoryMap());
}
}
}
DropCreateDatabaseIfModelChanges<PortalContext>()太暴力了
Code First數據庫遷移
改變原來類的結構后數據庫將發生錯誤提示
1.第一次建立數據庫遷移通過nugget來進行編輯
Package Manager Console-》Enable-Migrations -StartUpProjectName CodeFirst-》執行“Add-Migration FirstMigration”命令-》
執行“Update-Database”命令,更新數據庫架構
你的項目中將自動生成一個名為”Migrations“的文件夾,里面包含兩個文件: Configuration.cs和201308211510117_InitialCreate.cs(201308211510117是時間戳)。
Configuration.cs:是遷移配置代碼,一般我們不需要修改。
namespace CodeFirst.Migrations
{
using System;
using System.Data.Entity;
using System.Data.Entity.Migrations;
using System.Linq;
internal sealed class Configuration : DbMigrationsConfiguration<CodeFirst.OrderContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(CodeFirst.OrderContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
201308211510117_InitialCreate.cs:以代碼的形式記錄了本地數據庫的表結構定義。
設置自動遷移
有以下兩個參數可以對自動遷移進行設置:
1. AutomaticMigrationsEnabled:獲取或設置 指示遷移數據庫時是否可使用自動遷移的值。
2. AutomaticMigrationDataLossAllowed:獲取或設置 指示是否可接受自動遷移期間的數據丟失的值。如果設置為false,則將在數據丟失可能作為自動遷移一部分出現時引發異常。
原文:
http://www.mamicode.com/info-detail-872834.html
http://www.cnblogs.com/liupeng/p/4797046.html
http://www.guanggua.com/question/21573550-setting-unique-constraint-with-fluent-api.html
https://msdn.microsoft.com/en-us/data/jj591617.aspx#PropertyIndex
http://www.cnblogs.com/lyq2012/p/6183895.html
