如果這看起來像是重複的問題,請事先道歉。 This question是我能找到的最接近的,但它並不能真正解決我所面臨的問題。實體框架5工作單元模式 - 我應該在哪裏調用SaveChanges?
我在ASP.NET MVC4應用程序中使用實體框架5,並試圖實現工作單元模式。
我的工作類的單元實現IDisposable
,包含我DbContext
派生對象上下文類的一個實例,以及一些資源庫,其中的每一個從一個普通的基庫類派生暴露所有常見的存儲庫功能。
對於每個HTTP請求,Ninject創建Unit of Work類的單個實例並將其注入到控制器中,並在請求完成時自動處理它。
由於EF5將數據存儲抽象出來,Ninject管理對象上下文的生命週期,它似乎是消費代碼訪問內存中實體對象而不需要明確管理其持久性的完美方式。換句話說,爲了優化問題分離,我設想我的控制器操作方法能夠使用和修改存儲庫數據,而不需要以後明確地調用SaveChanges
。
我的第一個嘗試實現這個想法的嘗試是在修改數據的每個存儲庫基類方法中調用SaveChanges
。當然,我很快意識到這不是性能優化(特別是在對同一個方法進行多次連續調用時),也不適用於操作方法直接修改從存儲庫中檢索的對象的屬性的情況。
所以,我發展我的設計,以消除這些SaveChanges
過早的電話和工作實例的單元被設置在與一個單一的調用替換它們。這似乎是MVC中工作單元模式的最簡單實現,因爲一個工作單元自然適用於一個請求。
不幸的是,建築這個概念之後,我發現它的致命缺陷 - 的對象添加到或從DbContext
刪除是not reflected, even locally的事實,直到SaveChanges
被調用。
那麼,你有什麼想法,即消費代碼應該能夠使用對象而不必明確地堅持它們?而且,如果這個想法看起來有效,那麼用EF5實現它的最好方法是什麼?
非常感謝您的建議,
添
更新:根據@瓦希德的迴應,我加入了下面的一些測試代碼,顯示的一些情況中,它成爲消費代碼至關重要顯式調用SaveChanges
:
var unitOfWork = _kernel.Get<IUnitOfWork>();
var terms = unitOfWork.Terms.Entities;
// Purge the table so as to start with a known state
foreach (var term in terms)
{
terms.Remove(term);
}
unitOfWork.SaveChanges();
Assert.AreEqual(0, terms.Count());
// Verify that additions are not even reflected locally until committed.
var created = new Term { Pattern = "Test" };
terms.Add(created);
Assert.AreEqual(0, terms.Count());
// Verify that additions are reflected locally once committed.
unitOfWork.SaveChanges();
Assert.AreEqual(1, terms.Count());
// Verify that property modifications to entities are reflected locally immediately
created.Pattern = "Test2";
var another = terms.Single(term => term.Id == created.Id);
Assert.AreEqual("Test2", another.Pattern);
Assert.True(ReferenceEquals(created, another));
// Verify that queries against property changes fail until committed
Assert.IsNull(terms.FirstOrDefault(term => term.Pattern == "Test2"));
// Verify that queries against property changes work once committed
unitOfWork.SaveChanges();
Assert.NotNull(terms.FirstOrDefault(term => term.Pattern == "Test2"));
// Verify that deletions are not even reflected locally until committed.
terms.Remove(created);
Assert.AreEqual(1, terms.Count());
// Verify that additions are reflected locally once committed.
unitOfWork.SaveChanges();
Assert.AreEqual(0, terms.Count());
我覺得我和你有同樣的問題。來自NHibernate,我習慣於讓INSERT和DELETE語句直接進入數據庫,這樣當我稍後嘗試選擇對象時(在相同的DbContext會話中),我實際上得到了我的結果。我希望SaveChanges()只是提交事務,但看起來EF延遲了所有的INSERT/DELETE語句,直到調用SaveChanges()。你有沒有想過一個辦法來做它你想做的事(並且我認爲,我們想)? – efdee