Entity Framework新增記錄時獲取自增ID值
與Entity Framework相伴的日子痛並快樂著。今天和大家分享一下一個快樂,兩個痛苦。
先說快樂的吧。Entity Framework在將資料插入資料庫時,如果主鍵欄位是自增標識列,會將該自增值返回給實體物件對應的屬性。
比如下面新增部落格隨筆至資料庫的示例程式碼:
var blogPost =new BlogPost(){
Author ="部落格園",
Title ="程式設計師的網上家園"
};
using (BlogDbContext context =new BlogDbContext())
{
context.BlogPosts.Add(blogPost);
context.SaveChanges();
}
SaveChanges()之後,blogPost.ID的值就是資料庫中對應自增標識列的值。
看一下Entity Framework生成的SQL語句:
exec sp_executesql N'insert [dbo].[blog_Content]([Title],[Author])values (@0, @1)
select [ID]
from [dbo].[blog_Content]
where @@ROWCOUNT > 0 and [ID] = scope_identity()',
N'@0 nvarchar(128),@1 nvarchar(128),
EF通過scope_identity()獲取自增列的值,而且我們沒有對BlogPost的ID屬性進行任何設定,是EF智慧地判斷出ID就是自增標識列。
在以前沒有使用Entity Framework的時代,用的是儲存過程,儲存過程有一堆引數,實體物件的屬性值要一一對應地賦值給這些引數,執行儲存過程之後,還要通過ParameterDirection.Output的引數獲取自增ID的值。
現在,只要把東西交給Entity Framework,並和她說,把它放到資料庫中去。多省心!多快樂!
但是,自以為是的Entity Framework用這個特性給人快樂的同時,也給人帶來了一點痛苦。她認為只要實體類中有ID屬性,資料庫對應的是一定是自增標識列,真是夠自以為是的。當我們把部落格隨筆新增至資料庫後,準備用這個自增ID將隨筆內容新增至資料庫(隨筆內容儲存在單獨的資料庫,通過ID欄位與隨筆進行關聯,不是自增的),卻出現錯誤提示:
看看EF生成的SQL語句:
exec sp_executesql N'insert [dbo].[CNBlogsText_blog_PostBody]([Text])values (@0)
select [ID]
from [dbo].[CNBlogsText_blog_PostBody]
where @@ROWCOUNT > 0 and [ID] = scope_identity()',N'@0 nvarchar(128)',@0=N'幫助程式設計師用技術改變世界'
不是自增列,也來個scope_identity()。這麼聰明的Entity Framework,也會幹這樣的傻事。
還好,EF定製靈活的特性可以讓我們輕鬆化解這個痛苦,只要在BlogDbContext中新增下面的程式碼:
protectedoverridevoid OnModelCreating(DbModelBuilder modelBuilder){
modelBuilder.Entity<PostBody>().Property(p => p.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}
也可以通過在實體類屬性上加標記實現:
publicclass BlogPost{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
publicint ID { get; set; }
} 第二個痛苦是眾所周知的Entity Framework不支援列舉型別,雖然大家都知道,但還是想拿出晒晒,解解恨。
EF怎麼對待列舉型別的呢?對於實體類中實實在在存在的列舉型別的屬性,EF對它們視而不見,就當它不存在。
對於這個痛苦,目前無法化解(要等EF的下一版本),只能藉助旁邊左道減輕痛苦,請看“旁邊左道”之“移花接木”。
實體類中的程式碼:
publicclass BlogPost{
public BlogPostType PostType
{
get { return (BlogPostType)PostTypeEf; }
set { PostTypeEf = (int)value; }
}
publicint PostTypeEf { get; set; }
}