2010-06-25 37 views
6

實體框架4 - STE - 簡單DB與具有BlogID PK柱單個表博客...實體框架ObjectContext是否正確實現了工作單元模式?

var samplesDbEntities = new SamplesDBEntities(); 
var blogId = Guid.NewGuid(); 
samplesDbEntities.Blogs.AddObject(new Blog() { BlogID = blogId }); 
var objectSetResult = samplesDbEntities.Blogs 
             .Where(p => p.BlogID == blogId) 
             .SingleOrDefault(); 

(代碼執行的結果=> objectSetResult == NULL的最後一行之後)

AFAIK,ObjectContext是UoW模式的實現,在這種情況下,我想我應該從ObjectSet(Repository)返回的結果只是「標記爲瞬態」 有人可以解釋我做錯了什麼,以及爲什麼objectSetResult在這裏有null值?

(是的,我知道ObjectStateManager的,但對我來說是多爲上提到的建築問題的補丁的)

回答

1

您示例中違反的模式不是工作單元模式,而是身份映射。

工作單元跟蹤您的代碼對對象所做的更改,而不是您手動關注該對象。

標識映射模式實現對象上下文以使主鍵的單個值具有單個實體實例。

這對我來說很奇怪,但Entity Framework(以及LINQ 2 SQL)並沒有在每種情況下都映射對象標識,上面描述的情況就是這種情況之一。

4

您需要重新查詢對象之前調用

samplesDbEntities.SaveChanges(); 

var samplesDbEntities = new SamplesDBEntities(); 
var blogId = Guid.NewGuid(); 
samplesDbEntities.Blogs.AddObject(new Blog() { BlogID = blogId }); 

samplesDbEntities.SaveChanges(); 

var objectSetResult = samplesDbEntities.Blogs 
            .Where(p => p.BlogID == blogId) 
            .SingleOrDefault(); 

更新

爲什麼你沒有得到所添加的用戶早在objectSetResult是,調用數據庫查詢一個IQueryable對象結果的SingleOrDefault方法(實際SQL查詢字符串產生的原因根據「where」條件等),並且由於該對象不在數據庫中,因此不會返回。 但是,新對象附加到上下文,並且它的EntityState被設置爲「已添加」。根據MSDN,處於Added狀態的對象在ObjectStateEntry中沒有原始值。對象上下文中的對象狀態由ObjectStateManager管理。所以,如果你想檢查對象確實被連接,你可以通過調用GetObjectStateEntry取,

var samplesDbEntities = new SamplesDBEntities(); 
Blog blog = new Blog() { BlogID = Guid.NewGuid() }; 
samplesDbEntities.Blogs.AddObject("Blogs", blog); 

Blog addedBlog = (Blog)context.ObjectStateManager.GetObjectStateEntry(blog).Entity; 

還要注意的是檢索對象的EntityState是「添加」。總結一下 - 關於你最初的問題,關於它是否是UnitOfWork的正確實現,我不明白爲什麼不這樣做。它確實保留了對象列表並跟蹤更改等等。但是,您遇到的問題與您從基礎提供程序獲取數據而不是從當前附加到上下文。

+0

-1因爲這是不是在確切的問題上回答「實體框架ObjectContext是否正確實施工作單元模式?」 – Restuta 2010-06-25 15:25:56

+0

夠公平的。查看更新的答案。 – Yakimych 2010-06-25 17:04:24

+2

我的用例是實體在持久性發生之前被添加和檢索 - 如果我必須自己堅持每個實體而不是批量持久化,那麼UoW又有什麼意義呢? 至於更新代碼,你不覺得我必須知道我需要使用ObjectStateManager的事實不好(泄漏基礎設施)嗎? 不是我微不足道的樣品,但「得到」可以在完全不同的地方發生在哪裏我不知道,如果補上一的情況下。爲什麼這不會被封裝在OBjectSet本身內部(比如UoW應該這樣做)並且只是在持久化過程中被識別? – 2010-06-25 17:58:31

0

感謝您澄清您的觀點。我將此作爲另一個答案加入,因爲在這個問題上有很多話要說。

AFAIK,UoW沒有嚴格的普遍定義,所以當然這個話題是爭論的話題。我的觀點如下:

  1. 您正在添加一個實體到上下文,但試圖從數據庫中獲取它。結論是ObjectContext不是UoW的正確實現是不合邏輯的。

  2. 如果您將實體添加到上下文中,以便稍後在出於某種原因將其更改爲出於某種原因而退出之前,您未使用EF,因爲它是用來表示的。一般來說,你不應該使用ObjectStateManager要做到這一點,但你可以:

    Blog addedBlog = context. 
         ObjectStateManager. 
         GetObjectStateEntries(EntityState.Added). 
         Where(ent => (ent.Entity is Blog) && ((Blog)ent.Entity).BlogID == blogID). 
         Select(ent => ent.Entity as Blog). 
         SingleOrDefault(); 
    
  3. 工作的單位是一個上下文對象維護業務實體名單,跟蹤一個商業交易過程中改變他們的狀態。 EF ObjectContext是否可以做到這一點?是。它是否提供合理的語法來檢索狀態爲「已添加」的對象?不,但這不是對「正確」UoW實施的要求。別忘了 - EF是一個ORM,目標是跟蹤代碼中數據庫的變化,而不是代碼的不同部分之間的變化(這就是您的業務邏輯)。

和關於「什麼是UOW的點,如果我要堅持自身的每一個實體,而不是批量」 - 問題是,你可以一堆對象添加到上下文,然後通過調用SaveChanges一步一步地堅持它們。正如我已經提到的那樣,上下文並不意味着用於「攜帶」您的業務對象。但是,如果您願意,您可以從ObjectStateManager中檢索它們,而不必對數據庫進行更改。

+0

你說:「問題是,你可以一堆對象添加到上下文,然後通過調用的SaveChanges堅持他們都在一個去」 我有100%的同意(這就是我說的)。所描述的方式EF4的作品,我可以從我的代碼的不同部分添加具有相同ID的2個帖子 - 一切都很好,直到持久 - 當PK違反會發生。 我不需要EF4 *如何工作的更多解釋* - 我知道這一點,我認爲(架構)是有缺陷的。 好像SO問題是不是有這樣的討論,所以我會寫一個博客帖子有提供更多詳細信息,這... – 2010-06-27 10:52:34

+0

我投的問題被關閉的「太主觀了」,但我需要4個聲音的良好培養基爲了被關閉:) – 2010-06-27 10:54:01