EF Core 樂觀并發控制(并發令牌)

文章目錄

  • 前言
  • 一、樂觀并發的核心思想
  • 二、實現方法
    • 1)使用并發令牌(Concurrency Token)
    • 2)處理并發沖突
  • 三、工作原理
  • 四、適用場景
  • 五、與悲觀并發的對比
  • 六、最佳實踐
  • 總結


前言

Entity Framework (EF) Core 默認支持 樂觀并發控制(Optimistic Concurrency Control),它通過檢測數據沖突(而不是顯式加鎖)來保證數據一致性。

一、樂觀并發的核心思想

  1. 無鎖機制:允許多個事務同時讀取和修改數據,提交時檢查數據是否被其他事務修改。
  2. 沖突檢測:通過版本號(RowVersion)或字段值比較,如果數據已被修改,則拋出
    DbUpdateConcurrencyException

二、實現方法

1)使用并發令牌(Concurrency Token)

  1. 為實體添加一個并發標記字段(如 RowVersion),每次更新時檢查該字段是否與數據庫中的值一致。

  2. 示例:通過 [ConcurrencyCheck] 特性標記字段

    	public class House{public long Id { get; set; }public string Name{ get; set; }[ConcurrencyCheck]  // 標記為并發令牌public string Owner{ get; set; }}
    
  3. 示例:或通過 Fluent API 配置

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {modelBuilder.Entity<House>().Property(p => p.Owner)//.IsRowVersion()          // 自動映射為 SQL Server 的 `rowversion` 類型.IsConcurrencyToken();    // 標記為并發令牌
    }
    
    public class House
    {public long Id { get; set; }public string Name{ get; set; }		public string Owner{ get; set; }public byte[] RowVersion { get; set; }
    }
    public void Configure(EntityTypeBuilder<House> builder)
    {builder.ToTable("T_Houses");builder.Property(h=>h.Name).IsRequired();//builder.Property(h=>h.Owner).IsConcurrencyToken();builder.Property(h=>h.RowVersion).IsConcurrencyToken().IsRowVersion();
    }
    

2)處理并發沖突

  1. 當檢測到數據已被修改時,EF Core 會拋出 DbUpdateConcurrencyException,開發者需捕獲并處理沖突。

    try
    {var house = await context.Houses.FindAsync(houseId);house.Owner = "Tom";await context.SaveChangesAsync();
    }
    catch (DbUpdateConcurrencyException ex)
    {// 處理沖突var entry = ex.Entries.Single();var databaseValues = await entry.GetDatabaseValuesAsync();if (databaseValues == null){// 數據已被刪除Console.WriteLine("數據已被刪除!");}else{// 獲取當前數據庫中的值var currentValues = databaseValues.ToObject() as House;// 策略1:使用數據庫最新值覆蓋當前修改entry.OriginalValues.SetValues(databaseValues);// 策略2:合并值(手動處理沖突)// currentValues 是數據庫中的最新值// entry.Entity 是當前嘗試提交的值// 例如:保留用戶修改的某些字段,合并其他字段entry.Entity.Owner= "Tom";entry.Entity.RowVersion = currentValues.RowVersion;// 重新提交await context.SaveChangesAsync();}
    }
    

三、工作原理

  1. 查詢數據:讀取數據時,EF Core 會記錄并發令牌的原始值(如 RowVersion)。

  2. 更新數據:提交修改時,生成的 SQL 會包含 WHERE 條件,檢查并發令牌是否未被修改。

    UPDATE [T_Houses]
    SET [Owner] = @p0
    WHERE [Id] = @p1 AND [Owner] = @p2;
    
  3. 沖突檢測:如果受影響的行數為 0(即 RowVersion 不匹配),拋出異常。

四、適用場景

  1. 低沖突概率:適合大部分時間數據競爭較少的場景。
  2. 高吞吐需求:避免鎖機制的開銷,提升性能。
  3. 分布式系統:無鎖機制更適合跨服務的并發操作。

五、與悲觀并發的對比

樂觀并發悲觀并發
實現方式版本號或字段檢查(RowVersion、并發令牌)顯式加鎖(事務+鎖機制)
性能低沖突時更高效高競爭時可能更高效
復雜度EF Core 內置支持,自動檢測沖突需要手動管理鎖和事務
數據競爭可能需重試或合并數據強制串行化,避免沖突

六、最佳實踐

  1. 選擇并發令牌
    優先使用 RowVersion(自動遞增的二進制字段),而非業務字段。
    若使用業務字段(如 LastUpdatedTime),需確保其值在每次更新時被修改。
  2. 沖突處理策略
    客戶端優先:強制覆蓋數據庫的值(需謹慎)。
    數據庫優先:放棄當前修改,使用最新值。
    合并值:手動合并沖突字段(如用戶編輯的字段優先)。
  3. 重試機制
    在分布式系統中,可為關鍵操作添加重試邏輯(如 Polly 庫)。

總結

EF Core 的樂觀并發通過版本號或字段值檢測沖突,無需顯式加鎖,適合低競爭場景。通過 ConcurrencyCheckIsRowVersion() 配置并發令牌,并在沖突時通過 DbUpdateConcurrencyException 實現靈活的數據合并或重試邏輯。

  1. 樂觀并發控制能夠避免悲觀鎖帶來的性能、死鎖等問題,因此推薦使用并發控制而不是悲觀鎖。
  2. 如果有一個確定的字段要被進行并發控制,那么使用IsConcurrencyToken()把這個字段設置為并發令牌即可;
  3. 如果無法確定一個唯一的并發令牌列,那么就可以引入一個額外的屬性設置為并發令牌,并且在每次更新數據庫的時候,手動更新這一列的值;如果用的是SQL Server數據庫,那么也可以采用RowVersion列,設置為并發令牌列。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/75959.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/75959.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/75959.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

解決 FFmpeg 使用 C/C++ 接口時,解碼沒有 shell 快的問題(使用多線程)

一、問題 硬件設備為香橙派 5Plus&#xff0c;最近需要使用硬件視頻解碼來加速 YOLO 的檢測&#xff0c;shell 窗口的FFmpeg已經調通&#xff0c;詳見文章&#xff1a; 編譯支持 RKmpp 和 RGA 的 ffmpeg 源碼_rk3588 ffmpeg mpp-CSDN博客https://blog.csdn.net/plmm__/article…

工業控制網絡中常用的通信協議

1. 現場總線協議 Modbus 概述&#xff1a;Modbus 是最廣泛使用的工業協議之一&#xff0c;主要用于串行通信&#xff0c;支持主/從架構&#xff0c;通過 RS-232 或 RS-485 傳輸&#xff0c;也有基于以太網的 Modbus TCP 版本。特點&#xff1a;簡單易用&#xff0c;易于實現&am…

【Mac】npm error Error: EACCES: permission denied, mkdir‘/Users/...

問題描述&#xff1a;Mac電腦中的 vscode 下載依賴的時候提示沒有權限&#xff1a; 故障分析 首先賬號是有權限的&#xff0c;電腦就建了一個賬號是管理員&#xff1b;在桌面用shell直接執行命令npm init 命令可以執行成功&#xff0c;那么問題就出在vscodes上面了&#xff0…

Ruby 簡介

Ruby 簡介 引言 Ruby 是一種廣泛使用的動態、開源的編程語言,自 1995 年由日本程序員 Yukihiro Matsumoto(通稱 Matz)設計以來,它以其優雅的語法、強大的庫支持和跨平臺特性贏得了全球開發者的青睞。本文將詳細介紹 Ruby 的起源、特點、應用領域以及它在現代軟件開發中的…

[Qt5] QMetaObject::invokeMethod使用

&#x1f4e2;博客主頁&#xff1a;https://loewen.blog.csdn.net&#x1f4e2;歡迎點贊 &#x1f44d; 收藏 ?留言 &#x1f4dd; 如有錯誤敬請指正&#xff01;&#x1f4e2;本文由 丶布布原創&#xff0c;首發于 CSDN&#xff0c;轉載注明出處&#x1f649;&#x1f4e2;現…

Windows10清理機器大全集

Windows10清理機器大全集 寫在前面先這么個標題&#xff0c;逐漸補充禁止Update移除Microsoft Compatibility Telemetrywindows-defender-remover其它 寫在前面 看到標題&#xff0c;讀者已經就吐了。 我是說&#xff0c;我非常認可: IT從業者&#xff0c;如果你銀子比較充足&…

【AI】NLP

不定期更新&#xff0c;建議關注收藏點贊。 目錄 transformer大語言模型Google Gemma疫情網民情緒識別 整體框架 baseline構建 模型調參、模型優化、其他模型 數據trick、指標優化、magic feature 數據增強、偽標簽、遷移學習 模型融合sklearn中TFIDF參數詳解 頻率閾值可以去掉…

如何為 Debian 和 Kali 系統更換軟件源并更新系統

在 Linux 系統中&#xff0c;軟件源&#xff08;Software Repository&#xff09;是獲取軟件包和更新的核心途徑。然而&#xff0c;默認的軟件源可能會因為地理位置、網絡狀況等原因導致下載速度緩慢&#xff0c;甚至無法訪問。為了提升系統的軟件獲取效率&#xff0c;許多用戶…

android 一步完成 aab 安裝到手機

家人們誰懂&#xff01;在 Android 系統安裝 aab 應用超麻煩。滿心期待快速體驗&#xff0c;卻發現 aab 無法直裝&#xff0c;得先轉為 apks 格式&#xff0c;這過程復雜易錯。好不容易轉好&#xff0c;還得安裝 apks&#xff0c;一番折騰&#xff0c;時間與耐心全耗盡。別愁&a…

mac部署CAT監控服務

在 Mac 上部署美團點評開源的 CAT 監控服務端&#xff0c;可以按照以下步驟操作&#xff1a; 1. 環境準備 1.1 安裝依賴 確保已安裝以下工具&#xff1a; JDK 8&#xff08;建議 OpenJDK 11&#xff09; MySQL 5.7&#xff08;存儲監控數據&#xff09;&#xff08;8.0不支持…

C語言基礎:第10天筆記

內容提要 函數 函數的概述 函數的分類 函數的定義 形參和實參 函數的返回值 函數 函數的概述 函數&#xff1a;實現一定功能的&#xff0c;獨立的代碼模塊&#xff0c;函數是c程序的核心構成模塊&#xff0c;可以說c程序就是由眾多的函數組成&#xff0c;對于函數的使用…

集成開發環境革新:IntelliJ IDEA與Cursor AI的智能演進

集成開發環境革新&#xff1a;IntelliJ IDEA 與 Cursor AI 的智能演進 集成開發環境&#xff08;IDE&#xff09; 是軟件開發者必不可少的工具。一個優秀的 IDE 不僅能夠幫助編寫和調試代碼&#xff0c;還能集成版本控制和代碼優化等多種功能。如今&#xff0c;隨著人工智能&a…

【Django】教程-1-安裝+創建項目+目錄結構介紹

歡迎關注我&#xff01;后續會更新django教程。一周2-3更&#xff0c;歡迎跟進&#xff0c;本周會更新第一個Demo的單獨一個模塊的增刪改查【Django】教程-4-一個增刪改查的Demo【Django】教程-2-前端-目錄結構介紹【Django】教程-3-數據庫相關介紹 1.項目創建 1.1 安裝 Djan…

智能儀表板DevExpress Dashboard v24.2新版亮點:支持.NET 9

使用DevExpress BI Dashboard&#xff0c;再選擇合適的UI元素&#xff08;圖表、數據透視表、數據卡、計量器、地圖和網格&#xff09;&#xff0c;刪除相應參數、值和序列的數據字段&#xff0c;就可以輕松地為執行主管和商業用戶創建有洞察力、信息豐富的、跨平臺和設備的決策…

北斗導航 | 改進最小二乘殘差法的接收機自主完好性監測算法原理,公式,應用,研究綜述,matlab代碼

改進最小二乘殘差法的接收機自主完好性監測算法研究 摘要 本文針對傳統最小二乘殘差RAIM算法在復雜環境下檢測性能不足的問題,提出了一種基于加權抗差估計的改進算法。通過引入IGGⅢ權函數構建抗差最小二乘模型,結合滑動窗口方差估計和自適應閾值調整機制,顯著提升了算法對…

24、web前端開發之CSS3(一)

CSS3詳細講義 目錄 CSS3簡介CSS3核心特性選擇器盒模型背景與邊框文本樣式顏色與透明度過渡與動畫變換彈性盒布局網格布局媒體查詢多列布局字體與排版裝飾與效果性能優化新特性與兼容性CSS3實踐示例總結 一、CSS3簡介 CSS3&#xff08;Cascading Style Sheets, Level 3&#…

【Git “reset“ 命令詳解】

以下是關于 git reset 命令的完整博客文章內容&#xff1a; 本章目錄: 1. 命令簡介主要用途&#xff1a; 2. 命令的基本語法和用法語法格式&#xff1a;使用場景&#xff1a; 3. 命令的常用選項及參數選項示例&#xff1a;1. 使用 --soft 進行軟重置2. 使用 --mixed 進行混合重…

STM32 IIC通信

目錄 IIC簡介硬件電路連接I2C時序基本單元IIC完整數據幀MPU6050封裝硬件IIC內部電路 IIC簡介 IIC&#xff08;Inter-Integrated Circuit&#xff09;是 IIC Bus 簡稱&#xff0c;中文叫集成電路總線。它是一種串行通信總線&#xff0c;使用多主從架構&#xff0c;由飛利浦公司…

深入解析 TypeScript 核心配置文件 tsconfig.json

什么是 tsconfig.json&#xff1f; tsconfig.json 是 TypeScript 項目的中樞神經系統&#xff0c;它是 TypeScript 編譯器的配置文件&#xff0c;決定了整個項目的編譯規則、模塊解析方式和類型檢查策略。這個 JSON 文件通常位于項目根目錄&#xff0c;是 TypeScript 工程化開…

debug 筆記:llama 3.2 部署bug 之cutlassF: no kernel found to launch!

1 問題描述 按照官方的寫法 import torch from transformers import pipeline import os os.environ["HF_TOKEN"] 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 model_id "meta-llama/Llama-3.2-3B"pipe pipeline("text-generation", modelmode…