在EF實體框架之CodeFirst二中也提到數據庫里面一般包括表、列、約束、主外鍵、級聯操作、實體關系(E-R圖)、存儲過程、視圖、鎖、事務、數據庫結構更新等。前面幾篇博客把表、存儲過程、視圖這些算是總結了一下,這篇的話主要總結下基本的約定類型。
1.主鍵
在數據庫中主鍵是必不可少的,一般主鍵有業務主鍵和邏輯主鍵,而且主鍵有的還是聯合主鍵在code first中也可以通過約定的形式映射到數據庫——[Key]。
[Key] public int ProductID { get; set; }
默認主鍵約束:屬性名為[ID]或[類名 + ID]而且是整數int類型。對於int類型的主鍵默認是自增的,但有時候不想自增長,可以通過以下方式進行取消自動增長。
[Key] [DatabaseGenerated(DatabaseGeneratedOption.None)] public int ProductID { get; set; }
DatabaseGeneratedOption 有三個選項:
- DatabaseGeneratedOption.Computed: 在用 Code First 生成數據庫的時候你可以在 byte 或 timestamp 列上使用 DatabaseGenerated Annotation,否則就應該在數據庫存在的情況下使用因為如果數據庫不存在,此時 Code First 不知道為計算列(Computed Column)選擇使用什么樣的公式
- DatabaseGeneratedOption.Identity: 如果主鍵為 integer 型,則數據庫默認為自增長(效果等同於設置DatabaseGeneratedOption.Identity), 如果主鍵是 GUID 類型,則要顯式設置自增長
- DatabaseGeneratedOption.None: 如果不想自增長,可設置成 DatabaseGeneratedOption.None
[Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public Guid ProductID { get; set; }
對於聯合主鍵,就不能使用約定了,要使用Fluent API。
modelBuilder.Entity<Product>().HasKey(t=>new { t.ProductID,t.CategoryID});
2.列名
可以使用[Column]來指定列名以及映射到數據庫的數據類型。
[Column("Remark", TypeName ="text")] public string Remark { get; set; }
modelBuilder.Entity<Product>().Property(t => t.Remark).HasColumnName("Remark").HasColumnType("text");
3.數字類型長度及精度
對於decimal類型的數據,經常會保留幾位小數,decima(8,2)這樣子,在Data Annotation不支持該設置,需要通過Fluent API進行設置。
modelBuilder.Entity<Product>().Property(t => t.UnitPrice).HasPrecision(18, 2);
4.長度、數據類型及是否可空
在默認情況下,int類型的屬性生成的列名對應SQL SERVER列int類型;而String類型的屬性則對應SQL SERVER列的NVARCHAR類型。若類的字符串類型屬性未設置MaxLength,則生成對應的列類型為NVARCHAR(MAX)。如果想限制字符串的長度可以通過使用MaxLength(最長字符長度)、MinLength(最短字符長度)、StringLength(字符長度)來約定。用Required來標識,還可以設置是否可允許空字符串,顯示錯誤消息等。
[Column("Remark", TypeName ="text")] [Required,MaxLength(100),MinLength(20)] public string Remark { get; set; }
[StringLength(6)] public string PassWord { get; set; }
上面約定Remark最短20,最長100.但在Fluent API中並沒有MinLength,只有MaxLength。
5.Unicode編碼
對於string類型的默認都是映射成navrchar類型,如果想映射為varchar類型可以使用Fluent API的IsUnicode()設置。
modelBuilder.Entity<Product>().Property(t => t.Remark).IsRequired().IsUnicode().HasColumnName("Remark").HasColumnType("text");
6.忽略映射NotMapped
如果哪天想去掉一個屬性不想映射到數據庫,如果直接注釋掉,那可能在其他調用的地方就會報錯,沒有這個屬性,這時可以使用NotMapped,忽略映射到數據庫,這樣也不會報錯。同樣對於表也是。
[NotMapped] public string ProductName { get; set; }
[NotMapped] public class Product
modelBuilder.Entity<Product>().Ignore(t=>t.ProductName);
modelBuilder.Ignore<Product>();
7.Timestamp 和ConcurrencyCheck
這兩個約定都是為了並發控制,Timestamp 在類中只能存在一個,而ConcurrencyCheck是針對類中的一個或多個屬性。關於並發控制,這個會在以后詳細總結。
[Timestamp] public Byte[] TimeStamp { get; set; }
[Column("Remark", TypeName ="text")] [ConcurrencyCheck, Required,MaxLength(100),MinLength(20)] public string Remark { get; set; }
8.其他
復雜數據類型這個會放在下一篇博客中講解。關系特性:InverseProperty和ForeignKey會在關系映射中講解。
9.使用上面的約束映射了幾個比較特殊的到數據庫。