2011-03-22 51 views
0

在我的ASP.NET MVC應用程序中,我需要實現數據的持久性。我已經選擇了Entity Framework,因爲它能夠根據實體模型創建類,數據庫表和查詢​​,這樣我就不必手工編寫SQL表創建或Linq到SQL查詢。所以簡單是我的目標在ASP.NET MVC應用程序中使用EntityFramework的持久性

我的方法是創建模型,並創建一個自定義的HttpModule,並在每個請求處調用該對象,並在上下文中調用SaveChanges()。這讓我的生活變得非常艱難 - 實體框架一直在拋出非常奇怪的例外。有時它有效 - 沒有例外,但有時它沒有。首先,我試圖逐個解決問題,但是當我得到另一個問題時,我意識到我的一般方法可能是錯誤的。

那麼這是在ASP.NET MVC應用程序中實現持久性的一般實踐嗎?每次更改後,我只需撥打saveChanges?這不是沒有效率嗎?我不知道如何用Services patter做到這一點(服務與實體協同工作,所以我必須傳遞上下文實例給他們,這樣他們才能保存更改,如果他們做了一些)。

一些學習材料或教程的鏈接也受到讚賞。


注意:這個問題要求編程練習。我會問那些會認爲它含糊不清的人,記住它仍然在解決我非常特別的問題,正確的技術會在投票結束之前爲我節省很多技術問題。

+1

通過閱讀你的描述我有,你正在使用的上下文的單一共享實例不好的感覺,只是調用'SaveChanges'上http模塊中的結束請求期間的實例。 – 2011-03-22 22:48:35

+0

@Ladislav Mrnka你不好的感覺是對的,但現在我正在重建這個使用存儲庫模式。只需要弄清楚如何正確使用該模式。 – drasto 2011-03-23 04:40:22

+1

在這裏你有描述爲什麼你目前的解決方案沒有工作:http://stackoverflow.com/questions/3653009/entity-framework-and-connection-pooling/3653392#3653392 – 2011-03-23 05:46:28

回答

1

你只需要確保SaveChanges得到您的請求完成之前調用。在控制器的底部,動作是理想的地方。我的控制器動作通常是這樣的:

public ActionResult SomeAction(...) 
{ 
    _repository.DoSomething(); 
    ... 
    _repository.DoSomethingElse(); 
    ... 
    _repository.SaveChanges(); 
    return View(...); 
} 

這額外的好處是,如果一個異常被拋出,然後調用SaveChanges將不會被調用。您可以處理操作中的異常或Controller.OnException

+0

如何將該存儲庫保存更改到全局操作過濾器中,以便自動調用它,而無需在每個操作處手動編寫它?會有什麼缺點嗎? – drasto 2011-03-22 19:15:32

+1

問題在於如果(在我的示例中)'DoSomething()'完成並向存儲庫添加了有效更改。但是,然後'DoSomethingElse()'失敗,所以在這一點上,我不想再保存任何更改?如果您在所有請求後自動調用SaveChanges,則可能導致數據損壞。基本上上述模式是一個窮人的交易。在真實的交易中真正運行所有這些東西會更好。 – 2011-03-22 19:18:57

+0

@Matt格里爾沒有一些方法來檢查在動作過濾執行期間是否有異常?這將解決你正在解決的問題,它將仍然是'自動'... – drasto 2011-03-22 19:29:39

2

與調用一個存儲過程的次數(關於需要建立的連接數量)沒有多少差別。

名義上,您將對對象集進行所有更改,然後使用SaveChanges提交所有這些更改。

所以不是這樣:

mySet.Objects.Add(someObject); 
mySet.SaveChanges(); 
mySet.OtherObjects.Add(someOtherObject); 
mySet.SaveChanges(); 

你只需要做:

mySet.Objects.Add(someObject); 
mySet.OtherObjects.Add(someOtherObject); 
mySet.SaveChanges(); 
// Commits Both Changes 
1

通常你的數據訪問被一個實現了repsitory模式的對象包裝。然後調用存儲庫上的Save()方法。

喜歡的東西

var customer = customerRepository.Get(id); 
customer.FirstName = firstName; 
customer.LastName = lastName; 
customerRepository.SaveChanges(); 

該存儲庫然後由服務層提供視圖模型對象或DTO的

是不是那個小低效的包裹?

不要過早地優化。當您遇到性能問題時,請分析性能,找出原因並優化。重複。

更新

阿庫封裝數據的訪問,通常是一個單獨的實體。服務層包裝業務邏輯並可通過多個存儲庫訪問多個實體。它通常涉及'苗條'模型或DTO的。

一個例子可能是這樣獲得的發票清單爲客戶

public Customer GetCustomerWithInvoices(int id) { 

    var customer = customerRepository.Get(id); 
    var invoiceList = invoiceRepository.GetAllInvoicesFor(id); 

    return new Customer { 
    Customer = customer, 
    Invoices = invoiceList 
    }; 

} 
+0

你能給我一個關於服務層如何包裝存儲庫層的例子嗎? – drasto 2011-03-22 19:12:22

+1

@drasto我爲您添加了更新。 – 2011-03-22 19:31:59

相關問題