我使用EF核心1.0(以前稱爲廣告EF7)和ASP.NET核心1.0(以前稱爲ASP.NET 5),用於一個RESTful API 。實體框架核心1.0 Asp.Net核心中間件或過濾器的mvc工作單元
我希望有一些工作單元的作用範圍爲http請求,這樣當響應HTTP請求時,對DbContext所做的所有更改都將保存到數據庫中,或者不會保存(例如,如果有一些例外)。
在過去,我使用WebAPI2來實現NHibernate的這個目的,通過使用Action過濾器來開始執行動作的事務,並在執行的動作上結束事務並關閉會話。這其中,我的理解,已經實現了工作單位在http://isbn.directory/book/9781484201107
但是現在推薦我使用Asp.Net核心(與Asp.Net核心的mvc雖然這不應該是相關的)的方式和Entity Framework。
我認爲有插入ASP.NET管道(MVC)之前中間件是做事情的正確方法。因此,請求會去:
管道ASP.NET:MyUnitOfWorkMiddleware ==> MVC控制器==>倉庫==> MVC控制器==> MyUnitOfWorkMiddleware
我想有這個中間件保存的DbContext的如果沒有異常發生,那麼更改,以便在我的存儲庫實現中,我甚至不需要執行dbcontext.SaveChanges()
,並且所有內容都將像集中式事務一樣。在僞代碼,我想它會是這樣的:
class MyUnitOfWorkMiddleware
{
//..
1-get an instance of DbContext for this request.
try {
2-await the next item in the pipeline.
3-dbContext.SaveChanges();
}
catch (Exception e) {
2.1-rollback changes (simply by ignoring context)
2.2-return an http error response
}
}
這是否有意義?有人有類似的例子嗎?我無法找到任何好的做法或建議。如果我在我的MVC控制器級別上使用這種方法,我將無法訪問數據庫在創建新資源時創建的任何資源ID,因爲在保存dbContext更改之前不會生成ID(稍後在控制器完成執行後,在我的中間件管道中)。如果我需要訪問控制器中新創建的資源ID,該怎麼辦?
任何意見將不勝感激!
更新1:我發現我的做法有問題使用中間件來實現這一點,因爲在中間件的DbContext實例是不一樣的MVC(和存儲庫)一生中。看到問題Entity Framework Core 1.0 DbContext not scoped to http request
更新2:我還沒有找到一個好的解決辦法。基本上這些是我的選擇到目前爲止:
- 儘快保存DB中的更改。這意味着將其保存在存儲庫實現本身上。這種方法的問題是,對於一個Http請求,可能我想使用幾個存儲庫(即。e:將數據保存在數據庫中,然後將blob上傳到雲存儲),爲了獲得工作單元,我必須實現一個處理多個實體或甚至多個持久性方法的存儲庫(DB和Blob存儲),這會破壞整個目的
執行一個Action Filter,其中我將整個操作執行包裝在一個數據庫事務中。在控制器的動作執行結束時,如果沒有例外,我向數據庫提交chanches,但是如果有例外,我將回滾並放棄上下文。問題在於我的控制器的動作可能需要一個生成的實體的Id,以便將其返回給http客戶端(即:如果我得到一個POST/api/cars,我想返回一個帶有位置標題的201 Accepted,在/ api/cars/123和Id 123創建的新資源將不可用,因爲實體未保存在數據庫中,並且Id仍然是臨時的0)。通過以數據庫生成
return CreatedAtRoute("GetCarById", new { carId= carSummaryCreated.Id }, carSummaryCreated); //carSummaryCreated.Id would be 0 until the changes are saved in DB
我怎麼可能把整個控制器的動作包裹在一個數據庫事務,並在同一時間有任何可用的標識:例如,在控制器的一個POST命令請求採取行動從控制器的Http Response中返回它?或者.. 是否有任何優雅的方式來覆蓋http響應,並在數據庫更改已被提交後在操作篩選器級別設置Id?
更新3:按nathanaldensr「的評論,我能得到兩全其美的(包裹我的控制器的動作執行的DB交易_ UOW也知道DB前,甚至創造新的資源的ID提交更改)通過使用代碼生成的Guids而不是依賴數據庫來生成Guid。
這是一個很好的解決方案,謝謝 – iberodev
我喜歡你可以裝飾任何行動或控制器與工作單元過濾器在mvc生命週期中包裹交易中的一切。 – iberodev
問題仍然是當你需要一個實體ID來繼續在同一個http請求中做事時該怎麼做。在數據庫中提交更改之前,不會生成Id。通過這種方法,只有控制器完成執行後才能保存更改。 – iberodev