Entity Framework 插入數據 解決主鍵非自增問題


http://blog.csdn.net/educast/article/details/8632806

 

與Entity Framework相伴的日子痛並快樂着。今天和大家分享一下一個快樂,兩個痛苦。

先說快樂的吧。Entity Framework在將數據插入數據庫時,如果主鍵字段是自增標識列,會將該自增值返回給實體對象對應的屬性。

比如下面添加博客隨筆至數據庫的示例代碼:

復制代碼
var blogPost = new BlogPost()
{
Author = "博客園",
Title = "程序員的網上家園"
};
using (BlogDbContext context = new BlogDbContext())
{
context.BlogPosts.Add(blogPost);
context.SaveChanges();
return blogPost.ID;
}
復制代碼

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),',@0=N'程序員的網上家園',@1=N'博客園'

EF通過scope_identity()獲取自增列的值,而且我們沒有對BlogPost的ID屬性進行任何設置,是EF智能地判斷出ID就是自增標識列。

在以前沒有使用Entity Framework的時代,用的是存儲過程,存儲過程有一堆參數,實體對象的屬性值要一一對應地賦值給這些參數,執行存儲過程之后,還要通過ParameterDirection.Output的參數獲取自增ID的值。

現在,只要把東西交給Entity Framework,並和她說,把它放到數據庫中去。多省心!多快樂!

但是,自以為是的Entity Framework用這個特性給人快樂的同時,也給人帶來了一點痛苦。她認為只要實體類中有ID屬性,數據庫對應的是一定是自增標識列,真是夠自以為是的。當我們把博客隨筆添加至數據庫后,准備用這個自增ID將隨筆內容添加至數據庫(隨筆內容存儲在單獨的數據庫,通過ID字段與隨筆進行關聯,不是自增的),卻出現錯誤提示:

Cannot insert the value NULL into column 'ID', 
table 'CNBlogsText.dbo.blog_PostBody'; column does not allow nulls.

看看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中添加下面的代碼:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PostBody>().Property(p => p.ID)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
}

也可以通過在實體類屬性上加標記實現:

public class BlogPost
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ID { get; set; }
}

第二個痛苦是眾所周知的Entity Framework不支持枚舉類型,雖然大家都知道,但還是想拿出曬曬,解解恨。

EF怎么對待枚舉類型的呢?對於實體類中實實在在存在的枚舉類型的屬性,EF對它們視而不見,就當它不存在。

對於這個痛苦,目前無法化解(要等EF的下一版本),只能借助旁邊左道減輕痛苦,請看“旁邊左道”之“移花接木”。

實體類中的代碼:

復制代碼
public class BlogPost
{
public BlogPostType PostType
{
get { return (BlogPostType)PostTypeEf; }
set { PostTypeEf = (int)value; }
}
public int PostTypeEf { get; set; }
}
復制代碼

EF不認枚舉類型,但認int類型,所以增加個PostTypeEf,僅供EF專用,等EF的下一版本支持枚舉類型時再去掉。

BlogDbContext也要


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM