1. 程式人生 > >Entity FrameWork樂觀併發模式

Entity FrameWork樂觀併發模式

樂觀併發關係到樂觀的嘗試將entity儲存到資料庫時,希望entity資料在讀取之後,沒有被改變過。如果資料被改變過,將會丟擲一個異常,而你必須在嘗試再次儲存前解決這個衝突。本篇涵蓋了如何在EntityFrameWork中處理這樣的異常。本篇涉及的技術在對於使用Code First或是EF Desinger來建立模型時是同樣適用的

本篇並不適合討論樂觀併發,後續內容中假定讀者有一定的併發解決方案和通常任務展示模式的知識。

當你使用非關係型資料庫(外來鍵並不對映到entity上的一個屬性),比使用外來鍵關聯時來解決併發問題要困難的多。因此如果你準備實現併發解決方案建議你的應用在你的entity中使用外來鍵。後續所有的例子都假定你使用外來鍵關聯

當SaveChanges嘗試將一個使用外來鍵關聯的entity儲存時,檢測到一個樂觀併發異常時,會丟擲一個DbUpdateConcurrencyException異常

資料庫優先,使用Reload來解決樂觀併發異常

Reload方法用資料庫中的值來覆寫entity的當前值。entity將會以某種形式會給使用者,讓他們再次進行改動,並重新儲存,例如

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(1); 
    blog.Name = "The New ADO.NET Blog"
; bool saveFailed; do { saveFailed = false; try { context.SaveChanges(); } catch (DbUpdateConcurrencyException ex) { saveFailed = true; // Update the values of the entity that failed to save from the store
ex.Entries.Single().Reload(); } } while (saveFailed); }

模擬併發異常的一個好的方法是在SaveChanges上設定一個斷點,然後使用其他資料庫工具修改一個entity並儲存。你也可以在SaveChanges之前插入一行直接更新資料庫的SqlCommand,例如

context.Database.SqlCommand("UPDATE dbo.Blogs SET Name = 'Another Name' WHERE BlogId = 1");

DbUpdateConcurrencyException上的Entries方法返回更新失敗的entities的DbEntityEntry的例項。這個方法當前對於併發問題是返回單一的值,它也可能返回多個更新異常的值。一個可選的方案就是獲取所有的entities,併為他們每一個都執行Reload

以使用者優先來解決樂觀併發

上面的例子中使用資料庫優先,或是稱為儲存優先的Reload方法,因為在entity中的值被來自於資料的值覆蓋。有些時候你可能希望的行為正好相反,使用當前entity中的值來覆蓋資料庫中的值。這稱為使用者優先的方式是通過獲取當前資料庫中的值,並將他們設為entity的original值來實現的

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(1); 
    blog.Name = "The New ADO.NET Blog"; 

    bool saveFailed; 
    do 
    { 
        saveFailed = false; 
        try 
        { 
            context.SaveChanges(); 
        } 
        catch (DbUpdateConcurrencyException ex) 
        { 
            saveFailed = true; 

            // Update original values from the database 
            var entry = ex.Entries.Single(); 
            entry.OriginalValues.SetValues(entry.GetDatabaseValues()); 
        } 

    } while (saveFailed); 
}

Sometimes you may want to combine the values currently in the database with the values currently in the entity. This usually requires some custom logic or user interaction. For example, you might present a form to the user containing the current values, the values in the database, and a default set of resolved values. The user would then edit the resolved values as necessary and it would be these resolved values that get saved to the database. This can be done using the DbPropertyValues objects returned from CurrentValues and GetDatabaseValues on the entity’s entry. For example:

自定義樂觀併發異常解決方案

有時候你希望混合當前資料庫和當前entity的值。這通常需要一些自定義的邏輯或是介面,例如,你可能要使用表單來呈現包含當前值,資料庫值,最終值給使用者。使用者需要編輯最終值,並將最終值存入資料庫。這個步驟可以在entity上使用GetDatabaseValues或是CurrentValues返回的DbPropertyValues物件來完成。例如

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(1); 
    blog.Name = "The New ADO.NET Blog"; 

    bool saveFailed; 
    do 
    { 
        saveFailed = false; 
        try 
        { 
            context.SaveChanges(); 
        } 
        catch (DbUpdateConcurrencyException ex) 
        { 
            saveFailed = true; 

            // Get the current entity values and the values in the database 
            var entry = ex.Entries.Single(); 
            var currentValues = entry.CurrentValues; 
            var databaseValues = entry.GetDatabaseValues(); 

            // Choose an initial set of resolved values. In this case we 
            // make the default be the values currently in the database. 
            var resolvedValues = databaseValues.Clone(); 

            // Have the user choose what the resolved values should be 
            HaveUserResolveConcurrency(currentValues, databaseValues, resolvedValues); 

            // Update the original values with the database values and 
            // the current values with whatever the user choose. 
            entry.OriginalValues.SetValues(databaseValues); 
            entry.CurrentValues.SetValues(resolvedValues); 
        } 
    } while (saveFailed); 
} 

public void HaveUserResolveConcurrency(DbPropertyValues currentValues, 
                                       DbPropertyValues databaseValues, 
                                       DbPropertyValues resolvedValues) 
{ 
    // Show the current, database, and resolved values to the user and have 
    // them edit the resolved values to get the correct resolution. 
}

使用object來自定義樂觀併發異常解決方案

上述程式碼使用DbPropertyValues 例項來傳遞當前值,資料庫值,和最終值。更方便的方法是使用你的entity例項型別來完成。使用DbPropertyValues的ToObject和SetValues來完成,比如

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs.Find(1); 
    blog.Name = "The New ADO.NET Blog"; 

    bool saveFailed; 
    do 
    { 
        saveFailed = false; 
        try 
        { 
            context.SaveChanges(); 
        } 
        catch (DbUpdateConcurrencyException ex) 
        { 
            saveFailed = true; 

            // Get the current entity values and the values in the database 
            // as instances of the entity type 
            var entry = ex.Entries.Single(); 
            var databaseValues = entry.GetDatabaseValues(); 
            var databaseValuesAsBlog = (Blog)databaseValues.ToObject(); 

            // Choose an initial set of resolved values. In this case we 
            // make the default be the values currently in the database. 
            var resolvedValuesAsBlog = (Blog)databaseValues.ToObject(); 

            // Have the user choose what the resolved values should be 
            HaveUserResolveConcurrency((Blog)entry.Entity, 
                                       databaseValuesAsBlog, 
                                       resolvedValuesAsBlog); 

            // Update the original values with the database values and 
            // the current values with whatever the user choose. 
            entry.OriginalValues.SetValues(databaseValues); 
            entry.CurrentValues.SetValues(resolvedValuesAsBlog); 
        } 

    } while (saveFailed); 
} 

public void HaveUserResolveConcurrency(Blog entity, 
                                       Blog databaseValues, 
                                       Blog resolvedValues) 
{ 
    // Show the current, database, and resolved values to the user and have 
    // them update the resolved values to get the correct resolution. 
}

原文地址

相關推薦

Entity FrameWork樂觀併發模式

樂觀併發關係到樂觀的嘗試將entity儲存到資料庫時,希望entity資料在讀取之後,沒有被改變過。如果資料被改變過,將會丟擲一個異常,而你必須在嘗試再次儲存前解決這個衝突。本篇涵蓋了如何在EntityFrameWork中處理這樣的異常。本篇涉及的技術在對於使用

如何讓Entity Framework Db Frist模式下的Entity繼承關系?

clas use hide closed 相關 ase 創建 color 修改 1、使用DB Frist模式創建實體數據模型 Db Frist創建實體數據模型(創建edmx並不是重點,各位隨意即可),此處取名ZeroCodeDB,所得文件如圖所示; 其中紅框中的文件(Z

Entity Framework Code First 模式-建立一對多聯系

red ring 運行 not 例子 rod str 外鍵 ted 一、建立一對多聯系 使用的例子為Product與Category,一個種類(Product)對應多個商品(Product) 1.外鍵列名默認約定 在“一”這邊的實體增加一個集合屬性(public virtu

分享基於Entity Framework的Repository模式設計(附原始碼)

這篇文章介紹的是使用Entity Framework實現的Repositoy模式設計,歡迎各位拍磚. 閱讀目錄: 一、實現的思路和結構圖 二、Repository設計具體的實現程式碼 三、Repository設計的具體的使用 四、總結 一,實現的思路和結構圖 總結一下,Reposit

Entity Framework 資料併發訪問錯誤原因分析與系統架構優化

本文主要記錄近兩天針對專案發生的資料訪問問題的分析研究過程與系統架構優化,我喜歡說通俗的白話,高手輕拍1. 發現問題系統新模組上線後,使用頻率較高,故在實際使用和後期的問題重現測試中,產生了一下系列的資

Entity Framework 4.1 之六:樂觀併發

原文名稱:Entity Framework 4.1: Optimistic Concurrency (6) 這篇文章討論樂觀併發。 我們經常要面對多使用者併發訪問問題。這是因為人訪問機器的速度無法與高速的機器匹配,典型情況下,人需要大約一分鐘或者更多來填寫資料,而機器的交易處理通常只需要不到一

EF3:Entity Framework三種開發模式實現數據訪問

支持 代碼 sql blog flow cli guid 自動完成 main 前言 Entity Framework支持Database First、Model First和Code Only三種開發模式,各模式的開發流程大相徑庭,開發體驗完全不一樣。三種開發模式各有優缺

部落格園的大牛們,被你們害慘了,Entity Framework從來都不需要去寫Repository設計模式

本文將在技術層面挑戰園子裡的權威大牛們,言語不敬之處敬請包涵。本文旨為技術交流,歡迎拍磚。 園子裡面分享和推薦Entity Framework(以下簡稱EF)的Repository(倉儲)設計模式的文章真不少,其中還有很多大牛很詳細描述怎麼去實現。但是這些文章真是害人不淺。我現在想問問這些大牛們,你們現

Entity Framework 實體框架的形成之旅--基於泛型的倉儲模式的實體框架(1)

一些讀者也經常問問一些問題,不過最近我確實也很忙,除了處理日常工作外,平常主要的時間也花在了繼續研究微軟的實體框架(EntityFramework)方面了。這個實體框架加入了很多特性(例如LINQ等),目前也已經應用的比較成熟了,之所以一直沒有整理成一個符合自己開發模式的

擁抱Entity Framework的Code First開發模式

AppBox 是基於 FineUI 的通用許可權管理框架,包括使用者管理、職稱管理、部門管理、角色管理、角色許可權管理等模組。 從Subsonic到Entity Framework Subsonic最早釋出於2008年,當時他的無程式碼生成模式吸引了很多人的眼球,ActiveRecord模式的支援

Entity Framework技術系列之2:三種開發模式實現資料訪問

前言 Entity Framework支援Database First、Model First和Code Only三種開發模式,各模式的開發流程大相徑庭,開發體驗完全不一樣。三種開發模式各有優缺點,對於程式設計師沒有哪種模式最好,只有哪種模式更適合。接下來我將分別使用這

Entity Framework 的事務 DbTransaction

public null public static void Transaction() { myitEntities entity = null; DbTransaction tran = null; try { entity = new myitEntitie

Entity Framework的啟動速度優化

映射 自帶 1-1 man 同時 找到 優化 http target 剛開始的時候沒有太在意,但是隨著系統的發布,這種初次請求,或者閑置若幹時間後第一次請求的漫長等待使得App的體驗很差,很多時候App加載好半天數據都沒過來。如果前端沒處理好,還會導致App的假死。所以就花

利用Mocking Framework 單元測試Entity Framework

dom class exp detached 異步 dbr cnblogs kde num 一、前言   在實際編寫程序時,往往需要與數據庫打交道,在單元測試中直接使用數據庫又顯得太重,如果可以方便的編寫一些測試數據,這樣更易於檢測功能。如何模擬數據庫行為便是本篇的主題。微

Entity Framework Code First (三)Data Annotations

pos .cn ase image 希望 編程 create str length Entity Framework Code First 利用一種被稱為約定(Conventions)優於配置(Configuration)的編程模式允許你使用自己的 domain class

Asp.Net.Identity認證不依賴Entity Framework實現方式

aps 新建 create exc spn sharp 個數 blank aspnet Asp.Net.Identity為何物請自行搜索,也可轉向此文章http://www.cnblogs.com/shanyou/p/3918178.html 本來微軟已經幫我們將授權、認證

LINQ TO SQL和Entity Framework 的關系 你了解多少?

mode 最小 -m 發的 開發 content 內容 語言 account 1. LINQ TO SQL 和EF 特點: LINQ TO SQL和Entity Framework都是一種包含LINQ功能的ORM 也就是所謂的關系對象的映射。其中包括的有DBFrist

Entity Framework

引用 .aspx foreign for 必須 ons .com work key https://msdn.microsoft.com/en-us/library/jj679962(v=vs.113).aspx 1.引用Entity Framework 2.Data A

Entity Framework Code First to a New Database

con str open use lin log efi install mic 1. Create the Application To keep things simple we’re going to build a basic console applicati

Entity Framework Code First to an Existing Database

post red arc for ram .com als opened and 1. Create an Existing Database CREATE TABLE [dbo].[Blogs] ( [BlogId] INT IDENTITY (1, 1)