剛剛開始測試EF6及其異步功能。當我意識到他們不是線程安全時,男孩感到很驚訝。我有點認為那就是重點。

我已經有了自己的基於Task的擴展方法多年,但我在EF等待的是讓它們線程安全。

至少我的基於任務的功能lock為不互相干擾。 EF6甚至沒有那麼遠。但主要問題是我的代碼與他們的代碼共享。即嘗試發出異步查詢,然後在它完成之前嘗試訪問導航延遲加載的導航屬性(在同一上下文中預先加載的完全獨立的實體上)。這可以由UI或立即函數之外的其他代碼或其他十幾種場景觸發。

據我所知。 dbContext中僅有的兩個共享(實體之間)可變資源是連接和更改跟踪(緩存)。如果我們可以在功能性上添加鎖定,那麼我們就會有一個線程安全的上下文。

我們甚至可以分兩個階段完成。如果我們可以實現一個鎖定用於查詢數據庫的集中函數的提供程序。然後,任何非跟踪查詢 - 通過返回非實體(匿名)對像或通過調用AsNoTracking() - 將是線程安全的,並且即使另一個線程可能要求延遲加載的對象,使用異步函數調用也是安全的。

我們的可擴展性不會更糟,我們現在每個線程必須使用一個上下文,如果你試圖跳過一個等待引入一點並行或者正在工作的事情,甚至Async函數都不在桌面上系統(如wpf)可能會在等待的函數返回任務時觸發。

所以我的問題是。有沒有人實現這樣的提供者。或者有人願意和我一起工作嗎?

熱門答案

我認為你正面臨一個建築問題。您所描述的是UI直接使用EF對象的應用程序,它打破了“關注點分離”範例。

在我這邊,我在Model層上使用了海關線程安全緩存,讓一切都在Model層上發生。我使用眾所周知的AsyncLock在我的緩存上實現了線程安全性。

DbContext對像以及每個與EF CRUD相關的操作都具有非常有限的生命週期。每個CRUD操作都實例化它自己的DbContext,並將模型對象返回到緩存,然後,上下文被垃圾收集。我的應用程序使用緩存作為抽象層,緩存使用EF作為DB抽象層。

例如,在Objects上探索附加屬性是通過在Model層上實現自定義方法來完成的,該方法將對象Id作為參數,並將相關對象的列表返回到緩存。 UI詢問緩存,然後緩存詢問EF,然後一旦可用,對緩存的調用將對象返回到UI。就那麼簡單。

EntityFramework的設計不是線程安全的,因此無法以多線程方式使用它。 ( EF線程安全

您不必對DbContext進行並行訪問,而是必須構建一個可以多線程方式訪問的Model層。並且您的模型可以對您的DB進行多個並行調用,但請記住,每個調用必須實例化並保留它自己的DbContext。在每次調用結束時,必須處理相關的DbContext。

DbContext實際上很快實例化,唯一的缺點是網絡延遲。這就是內存緩存是個好主意的原因。




許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
這個KB合法嗎? 是的,了解原因