Data annotation特性是在.NET 3.5中引進的,給ASP.NET web應用中的類提供了一種添加驗證的方式。Code First允許你使用代碼來建立Entity Framework模型,同時允許用Data annotation特性來配置類和屬性的某些特性。
其實在前面的幾篇文章中,有用到幾個,在這一篇裡,進行一次比較全面的介紹
Key
EF架構要求每個實體必須有主鍵欄位,他需要根據這個主鍵欄位跟蹤實體。CodeFirst方法在建立實體時,也必須指定主鍵欄位,預設情況下屬性被命名為ID、id或者[ClassName]Id,將映射為資料表中的主鍵如果沒有類似的命名,並且也未顯示指明主鍵,則產生失敗,引發異常。如果想要自訂主鍵列名,則可以使用Key注釋
[Key]
publicint MyId { get; set; }
Required
當要求資料庫在欄位,不可為空時
[Required]
publicstring BookTitle { get; set; }
MaxLength 、MinLength
設定資料庫欄位的長度範圍
[MaxLength(10),MinLength(6)]
publicstring Password { get; set; }
NotMapped
當建立資料表時,用此屬性修飾的屬性,不會被建立為資料表欄位
[NotMapped]
publicint MyProperty { get; set; }
ComplexType
Complex屬性是將一個對象做為另一個對象的屬性。映射到資料庫中則子物件表現為多個屬性欄位。具體可參考:EF架構step by step(6)—處理實體complex屬性
[ComplexType]
publicclass Publisher
{
publicstring PublisherName { get; set; }
publicstring PublisherAddress { get; set; }
}
ConcurrencyCheck
並發檢查允許你標識一個或者多個屬性在實體更新時,要進行檢查是否與原實體一致。並發檢查依懶於OriginalValue,在WEB應用程式中,通常是某一使用者擷取資料實體後,會與資料庫中斷連線,這時,如果另一使用者也獲得了實體並進行了更新新操作,那麼當最初使用者進行再更新時,會自動進行並發檢查,根據被標識ConcurrencyCheck屬性的OriginalValue,判斷原實體是否存在。如果不存在,則在SaveChanges方法是會引發一個異常。
下面的例子是Book實體的BookTitle屬性被標識為ConcurrencyCheck。
[Required,ConcurrencyCheck]
publicstring BookTitle { get; set; }
則下面代碼類比並發現象:
Book book = db.Books.Find(1);
//顯示表明資料實體被修改
db.Entry(book).State = System.Data.EntityState.Modified;
db.Entry(book).Property(b => b.BookTitle).OriginalValue ="DataAnnotations";
//這麼代碼會引發異常
db.SaveChanges();
引發異常如:
用SQL Profile監控,資料庫執行了如下
update[dbo].[MyBook]
set[BookTitle]=@0
where (([MyId]=@1) and ([BookTitle]=@2))
', N'@0nvarchar(4000),@1int,@2nvarchar(4000)',
@0 = N'EF4.1 Code First', @1 = 1, @2 = N'DataAnnotations'
TimeStamp 與 DatabaseGenerated
TimeStamp是比ConcurrencyCheck更通用的監控並發的欄位,在實體中通常一個類型為位元組數組的欄位表示,一個實體類只能有一個TimeStamp欄位,並且他通常與DatabaseGenerated聯合使用,DatabaseGenerated表明是由資料庫自動產生,他需要DatabaseGeneratedOption枚舉來做為資料庫產生時參數,DatabaseGeneratedOption枚舉包含三個值 Computed 由資料庫自動計算,Identity自動成長,None資料庫不做處理。
[Timestamp,DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public Byte[] TimeStamp { get; set; }
TimeStamp與ConcurrencyCheck用法類似
Book book = db.Books.Find(1);
//類比另一個使用者對同一資料實體進行更新
db.Database.ExecuteSqlCommand("update mybook set Booktitle='EF' where MyId=1");
book.BookTitle ="New Title";
db.SaveChanges();
同樣,在SaveChanges()時,也會引發DbUpdateConcurrencyException。
Table
CodeFirst 方法預設以實體類名複數形式做為資料表名,Table注釋允許自訂表格名
[Table("MyBook")]
publicclass Book
Column
CodeFirst 方法預設以實體類屬性名稱做為列名,Column注釋允許自定列名及資料類型
[Column("BlogDescription", TypeName ="ntext")]
publicstring Description { get; set; }
好,來個綜合樣本,看一下運行結果,對照理解一下
[Table("MyBook")]
publicclass Book
{
[Key]
publicint MyId { get; set; }
[MaxLength(10), MinLength(6)]
publicstring KeyWord { get; set; }
[Required,MaxLength(50)]
publicstring BookTitle { get; set; }
[NotMapped]
publicint MyProperty { get; set; }
public Publisher Publisher { get; set; }
[Column("BlogDescription", TypeName ="ntext")]
publicstring Description { get; set; }
[Timestamp,DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public Byte[] TimeStamp { get; set; }
}
[ComplexType]
publicclass Publisher
{
publicstring PublisherName { get; set; }
publicstring PublisherAddress { get; set; }
}
產生資料表
Data annotation特性是在.NET 3.5中引進的,給ASP.NET web應用中的類提供了一種添加驗證的方式。Code First允許你使用代碼來建立Entity Framework模型,同時允許用Data annotation特性來配置類和屬性的某些特性。
其實在前面的幾篇文章中,有用到幾個,在這一篇裡,進行一次比較全面的介紹
Key
EF架構要求每個實體必須有主鍵欄位,他需要根據這個主鍵欄位跟蹤實體。CodeFirst方法在建立實體時,也必須指定主鍵欄位,預設情況下屬性被命名為ID、id或者[ClassName]Id,將映射為資料表中的主鍵如果沒有類似的命名,並且也未顯示指明主鍵,則產生失敗,引發異常。如果想要自訂主鍵列名,則可以使用Key注釋
[Key]
publicint MyId { get; set; }
Required
當要求資料庫在欄位,不可為空時
[Required]
publicstring BookTitle { get; set; }
MaxLength 、MinLength
設定資料庫欄位的長度範圍
[MaxLength(10),MinLength(6)]
publicstring Password { get; set; }
NotMapped
當建立資料表時,用此屬性修飾的屬性,不會被建立為資料表欄位
[NotMapped]
publicint MyProperty { get; set; }
ComplexType
Complex屬性是將一個對象做為另一個對象的屬性。映射到資料庫中則子物件表現為多個屬性欄位。具體可參考:EF架構step by step(6)—處理實體complex屬性
[ComplexType]
publicclass Publisher
{
publicstring PublisherName { get; set; }
publicstring PublisherAddress { get; set; }
}
ConcurrencyCheck
並發檢查允許你標識一個或者多個屬性在實體更新時,要進行檢查是否與原實體一致。並發檢查依懶於OriginalValue,在WEB應用程式中,通常是某一使用者擷取資料實體後,會與資料庫中斷連線,這時,如果另一使用者也獲得了實體並進行了更新新操作,那麼當最初使用者進行再更新時,會自動進行並發檢查,根據被標識ConcurrencyCheck屬性的OriginalValue,判斷原實體是否存在。如果不存在,則在SaveChanges方法是會引發一個異常。
下面的例子是Book實體的BookTitle屬性被標識為ConcurrencyCheck。
[Required,ConcurrencyCheck]
publicstring BookTitle { get; set; }
則下面代碼類比並發現象:
Book book = db.Books.Find(1);
//顯示表明資料實體被修改
db.Entry(book).State = System.Data.EntityState.Modified;
db.Entry(book).Property(b => b.BookTitle).OriginalValue ="DataAnnotations";
//這麼代碼會引發異常
db.SaveChanges();
引發異常如:
用SQL Profile監控,資料庫執行了如下
update[dbo].[MyBook]
set[BookTitle]=@0
where (([MyId]=@1) and ([BookTitle]=@2))
', N'@0nvarchar(4000),@1int,@2nvarchar(4000)',
@0 = N'EF4.1 Code First', @1 = 1, @2 = N'DataAnnotations'
TimeStamp 與 DatabaseGenerated
TimeStamp是比ConcurrencyCheck更通用的監控並發的欄位,在實體中通常一個類型為位元組數組的欄位表示,一個實體類只能有一個TimeStamp欄位,並且他通常與DatabaseGenerated聯合使用,DatabaseGenerated表明是由資料庫自動產生,他需要DatabaseGeneratedOption枚舉來做為資料庫產生時參數,DatabaseGeneratedOption枚舉包含三個值 Computed 由資料庫自動計算,Identity自動成長,None資料庫不做處理。
[Timestamp,DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public Byte[] TimeStamp { get; set; }
TimeStamp與ConcurrencyCheck用法類似
Book book = db.Books.Find(1);
//類比另一個使用者對同一資料實體進行更新
db.Database.ExecuteSqlCommand("update mybook set Booktitle='EF' where MyId=1");
book.BookTitle ="New Title";
db.SaveChanges();
同樣,在SaveChanges()時,也會引發DbUpdateConcurrencyException。
Table
CodeFirst 方法預設以實體類名複數形式做為資料表名,Table注釋允許自訂表格名
[Table("MyBook")]
publicclass Book
Column
CodeFirst 方法預設以實體類屬性名稱做為列名,Column注釋允許自定列名及資料類型
[Column("BlogDescription", TypeName ="ntext")]
publicstring Description { get; set; }
好,來個綜合樣本,看一下運行結果,對照理解一下
[Table("MyBook")]
publicclass Book
{
[Key]
publicint MyId { get; set; }
[MaxLength(10), MinLength(6)]
publicstring KeyWord { get; set; }
[Required,MaxLength(50)]
publicstring BookTitle { get; set; }
[NotMapped]
publicint MyProperty { get; set; }
public Publisher Publisher { get; set; }
[Column("BlogDescription", TypeName ="ntext")]
publicstring Description { get; set; }
[Timestamp,DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public Byte[] TimeStamp { get; set; }
}
[ComplexType]
publicclass Publisher
{
publicstring PublisherName { get; set; }
publicstring PublisherAddress { get; set; }
}
產生資料表