跨多個數據上下文使用 POCO 動態代理跟踪 Entity Framework 4.0 中的更改
我開始搞亂 EF 4.0 因為我對 POCO 的可能性感到好奇……我想模擬斷開連接的 Web 環境並編寫了以下程式碼來模擬這個:
- 在數據庫中保存一個測試對象。
- 檢索測試對象
- 處理與我用來檢索它的測試對象關聯的 DataContext
- 更新測試對象
- 創建一個新的數據上下文並持久化測試對像上的更改,這些更改在針對我的 POCO 對像生成的 DynamicProxy 中自動跟踪。
問題是當我在上面的 Test 方法中呼叫 dataContext.SaveChanges 時,沒有應用更新。當我檢查它的 EntityStateTracker 時,testStore 實體顯示“已修改”狀態,但是當我在新的 dataContext 的 Stores 屬性中查看它時,它不再被修改。我原以為在新的 dataContext 上呼叫 Attach 方法也會使對象的“已修改”狀態結束,但情況似乎並非如此。有什麼我想念的嗎?我肯定正在使用 DynamicProxies 與自我跟踪 POCO 合作。
private static void SaveTestStore(string storeName = "TestStore") { using (var context = new DataContext()) { Store newStore = context.Stores.CreateObject(); newStore.Name = storeName; context.Stores.AddObject(newStore); context.SaveChanges(); } } private static Store GetStore(string storeName = "TestStore") { using (var context = new DataContext()) { return (from store in context.Stores where store.Name == storeName select store).SingleOrDefault(); } } [Test] public void Test_Store_Update_Using_Different_DataContext() { SaveTestStore(); Store testStore = GetStore(); testStore.Name = "Updated"; using (var dataContext = new DataContext()) { dataContext.Stores.Attach(testStore); dataContext.SaveChanges(SaveOptions.DetectChangesBeforeSave); } Store updatedStore = GetStore("Updated"); Assert.IsNotNull(updatedStore); }
正如您稍後所說,您使用的是 POCO 生成器,而不是自跟踪實體生成器。
我也試過了,很困惑。代理類似乎沒有按預期工作,並且可能存在錯誤。然後再一次。MSDN 上的範例都沒有嘗試這樣的事情,當他們引用應用程序不同層的更新時(就像我們在這裡所做的那樣),他們使用自我跟踪實體,而不是 POCO 代理。
我不確定這些代理是如何工作的,但它們似乎確實儲存了某種狀態(我設法在私有屬性中找到了“修改”狀態)。但似乎這個屬性被完全忽略了。當您將屬性附加到上下文時,上下文會向 ObjectStateManager 添加一個條目,並將進一步的狀態更新儲存在其中。此時,如果您進行更改 - 它將被註冊並應用。
問題是,當您附加實體時 - 來自代理的已修改狀態不會傳輸到上下文中的狀態管理器。此外,如果您使用 context.Refresh() 更新將被覆蓋並被遺忘!即使您將 RefreshMode.ClientWins 傳遞給它。我嘗試將對象狀態的狀態屬性設置為已修改,但無論如何它都被覆蓋了,並且恢復了原始設置..
似乎 EF 中沒有錯誤,唯一的方法是使用這樣的東西:
using (var db = new Entities()) { var newUser = (from u in db.Users where u.Id == user.Id select u).SingleOrDefault(); db.Users.ApplyCurrentValues(user); db.SaveChanges(); }這裡還有一件事
似乎 POCO 只是不支持您正在尋找的方法,並且正如我所期望的那樣,創建了自我跟踪實體來解決您正在測試的情況,而 POCO 的代理僅在他們創建的上下文中跟踪更改。或者所以它看起來…