摘自:http://www.cnblogs.com/nianming/archive/2012/11/07/2757997.html Entity Framework Code First的預設行為是使用一系列約定將POCO類映射到表。然而,有時候,不能也不想遵循這些約定,那就需要重寫它們。重寫預設 ...
摘自:http://www.cnblogs.com/nianming/archive/2012/11/07/2757997.html
Entity Framework Code First的預設行為是使用一系列約定將POCO類映射到表。然而,有時候,不能也不想遵循這些約定,那就需要重寫它們。重寫預設約定有兩種方式:Data Annotations和FluentAPI。Data Annotations在功能上是Fluent API的子集,在一些映射場景下使用Annotations不能達到重寫的目的,因此本篇文章中使用Fluent API配置屬性。
一、Fluent API配置屬性
Code First Fluent API通常情況下是在DbContext的派生類中重寫OnModelCreating方法。
1.配置Length
Length用來描述數組的長度,當前包括string和Byte數組。
預設約定:Code First對string或byte數組的預設長度約定是max。註意:Sql Server Compact中預設最大數組長度是4000。
重寫約定:使用HasMaxLength(nn),參數為可空整數。
1: Property(t => t.Name).HasMaxLength(50);
另外關於Length的Fluent API還有下麵2個:
IsFixedLength(),配置屬性為固定長度。
IsMaxLength(),配置屬性為資料庫提供程式允許的最大長度。
2.配置Data Type
Data Type表示將.NET類型映射到的資料庫的數據類型。
預設約定:列的數據類型由使用的資料庫提供程式決定。以SQL Server為例:String->nvarchar(max),Integer->int,Byte[]->varbinary(max),Boolean->bit。
重寫約定:使用HasColumnType(“xxx”),下麵列子的Photo是byte[]類型,配置映射到image數據類型:
1: Property(t => t.Photo).HasColumnType("image");
3.配置允許為空和不允許為空
預設約定:主鍵屬性不允許為空,引用類型(String,array)允許為空,值類型(所有的數字類型,Datetime,bool,char)不允許為空,可空的值類型Nullable<T>允許為空。
重寫約定:使用IsRequired()配置不允許為空,使用IsOptional()配置允許為空。下麵配置Name屬性為不為空:
1: Property(t => t.Name).IsRequired();
4.配置屬性到指定列
預設約定:映射到與屬性名相同的列。
重寫約定:使用Property(t=>t.屬性名).HasColumnName(“xxx”)。下麵配置Name映射到DepartmentName:
1: Property(t => t.Name).HasColumnName("DepartmentName");
5.配置主鍵
預設約定:(1)屬性名為ID或Id的預設為主鍵
(2)類名+ID或類名+Id預設為主鍵 (其中ID或Id的優先順序大於類名+ID或類名+Id)
重寫約定:使用HasKey(t=>t.屬性名)。下麵將BlogId配置為主鍵:
1: HasKey(t => t.BlogId);
6.配置組合主鍵
下麵的例子將DepartmentId和Name屬性組合作為Department類型的主鍵:
1: HasKey(t => new { t.DepartmentId, t.Name });
7.配置Database-Generated
預設約定:整型鍵:Identity。
重寫約定:使用Property(t => t.屬性名).HasDatabaseGeneratedOption(DatabaseGeneratedOption)。
DatabaseGeneratedOption枚舉包括三個成員:
(1) None:資料庫不生成值
(2) Identity:當插入行時,資料庫生成值
(3) Computed:當插入或更新行時,資料庫生成值
整型預設是Identity,資料庫生成值,自動增長,如果不想資料庫自動生成值,使用DatabaseGeneratedOption.None。
Guid類型作為主鍵時,要顯示配置為DatabaseGeneratedOption.Identity。
8.配置TimeStamp/RowVersion的樂觀併發
預設約定:這個沒有預設約定。
配 置:使用Property(t=>t.屬性名).IsRowVersion()
1: Property(t => t.RowVersion).IsRowVersion();
9.不配置TimeStamp的樂觀併發
有些資料庫不支持RowVersion類型,但是又想對資料庫的一個或多個欄位併發檢查,這時可以使用Property(t=>t.屬性名).IsConcurrencyToken(),下麵的例子將SocialSecurityNumber配置為併發檢查。
1: Property(t => t.SocialSecurityNumber).IsConcurrencyToken();
10.配置String屬性是否支持Unicode內容
預設約定:預設string是Unicode(在SQL Server中是nvarchar)的。
重寫約定:下麵的例子使用IsUnicode()方法將Name屬性配置為varchar類型的。
1: Property(t => t.Name).IsUnicode(false);
11.配置小數的精度和小數位數
預設約定:小數是(18,2)
配 置:使用Property(t=>t.屬性名).HasPrecision(n,n)
1: public decimal MilesFromNearestAirport { get; set; }
12.複雜類型
預設複雜類型有以下規則:
(1) 複雜類型沒有主鍵屬性 (2) 複雜類型只能包含原始屬性。 (3)在其他類中使用複雜類型時,必須表示為非集合類型。
使用DbModelBuilder.ComplexType方法顯示配置為複雜類型:
1: modelBuilder.ComplexType<Address>();
13.嵌套的複雜類型
嵌套的複雜類型只需顯示配置外層,內層自動繼承複雜類型的約定。
14.配置複雜類型的屬性
配置複雜類型的屬性和配置實體屬性一樣,具體參考下麵的實例。
二、配置屬性實例
下麵直接給出代碼,代碼上都有註釋。註:下麵的實體主要是為了演示用
1: //實體
2: public class Trip
3: {
4: public Guid Identifier { get; set; }
5: public DateTime StartDate { get; set; }
6: public DateTime EndDate { get; set; }
7: public decimal CostUSD { get; set; }
8: public string Description { get; set; }
9: public byte[] RowVersion { get; set; }
10: }
11:
12: //複雜類型
13: public class Address
14: {
15: public int AddressId { get; set; }
16: public string StreetAddress { get; set; }
17: public string City { get; set; }
18: public string State { get; set; }
19: public string ZipCode { get; set; }
20: }
21:
22: //複雜類型
23: public class PersonalInfo
24: {
25: public Measurement Weight { get; set; }
26: public Measurement Height { get; set; }
27: public string DietryRestrictions { get; set; }
28: }
29:
30: //複雜類型
31: public class Measurement
32: {
33: public decimal Reading { get; set; }
34: public string Units { get; set; }
35: }
36:
37: //實體
38: public class Person
39: {
40: public Person()
41: {
42: Address = new Address();
43: Info = new PersonalInfo()
44: {
45: Weight = new Measurement(),
46: Height = new Measurement()
47: };
48: }
49:
50: public int PersonId { get; set; }
51: public int SocialSecurityNumber { get; set; }
52: public string FirstName { get; set; }
53: public string LastName { get; set; }
54: public Address Address { get; set; }
55: public byte[] Photo { get; set; }
56: public PersonalInfo Info { get; set; }
57: public byte[] RowVersion { get; set; }
58: }
59:
60: //對實體Trip的配置,繼承自EntityTypeConfiguration<T>
61: public class TripConfiguration : EntityTypeConfiguration<Trip>
62: {
63: public TripConfiguration()
64: {
65: //配置Identifier映射到TripId列,並設為主鍵,且預設值為newid()
66: HasKey(t => t.Identifier).Property(t => t.Identifier).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).HasColumnName("TripId");
67: //配置CostUSD的精度為20,小數位數為3
68: Property(t => t.CostUSD).HasPrecision(20, 3);
69: //配置Description的長度為500
70: Property(t => t.Description).HasMaxLength(500);
71: //配置RowVersion樂觀併發檢查
72: Property(t => t.RowVersion).IsRowVersion();
73: }
74: }
75:
76: //對實體Person的配置,繼承自EntityTypeConfiguration<T>
77: public class PersonConfiguration : EntityTypeConfiguration<Person>
78: {
79: public PersonConfiguration()
80: {
81: //配置SocialSecurityNumber不允許為空且樂觀併發檢查
82: Property(t => t.SocialSecurityNumber).IsRequired().IsConcurrencyToken();
83: //配置FirstName不允許為空
84: Property(t => t.FirstName).IsRequired();
85: //配置LastName不允許為空
86: Property(t => t.LastName).IsRequired();
87: //配置Photo映射到資料庫的數據類型為image
88: Property(t => t.Photo).HasColumnType("image");
89: //配置RowVersion樂觀併發檢查
90: Property(t => t.RowVersion).IsRowVersion();
91: }
92: }
93:
94: //對複雜類型Address的配置,繼承自ComplexTypeConfiguration<T>
95: public class AddressConfiguration : ComplexTypeConfiguration<Address>
96: {
97: public AddressConfiguration()
98: {
99: //配置AddressId映射到AddressId列
100: Property(t => t.AddressId).HasColumnName("AddressId");
101: //配置StreetAddress長度為100並映射到StreetAddrress列
102: Property(t => t.StreetAddress).HasMaxLength(100).HasColumnName("StreetAddress");
103: //配置State長度為50並映射到State列
104: Property(t => t.State).HasMaxLength(50).HasColumnName("State");
105: //配置City長度為50並映射到City列
106: Property(t => t.City).HasMaxLength(50).HasColumnName("City");
107: //配置ZipCode映射到ZipCode列,不支持Unicode內容,並設為固定長度為6
108: Property(t => t.ZipCode).IsUnicode(false).IsFixedLength().HasMaxLength(6).HasColumnName("ZipCode");
109: }
110: }
111:
112: //對複雜類型PersonalInfo的配置,繼承自ComplexTypeConfiguration<T>
113: public class PersonalInfoConfiguration : ComplexTypeConfiguration<PersonalInfo>
114: {
115: public PersonalInfoConfiguration()
116: {
117: //配置DietryRestrictions長度為100
118: Property(t => t.DietryRestrictions).HasMaxLength(100);
119: }
120: }
121:
122: public class BreakAwayContext : DbContext
123: {
124: public DbSet<Trip> Trips { get; set; }
125: public DbSet<Person> People { get; set; }
126:
127: protected override void OnModelCreating(DbModelBuilder modelBuilder)
128: {
129: //註冊配置
130: modelBuilder.Configurations.Add(new TripConfiguration());
131: modelBuilder.Configurations.Add(new PersonConfiguration());
132: modelBuilder.Configurations.Add(new AddressConfiguration());
133: modelBuilder.Configurations.Add(new PersonalInfoConfiguration());
134: base.OnModelCreating(modelBuilder);
135: }
136: }
最後生成的資料庫結構,如下圖所示:
Trips表
People表