在多用户同时操作数据库的场景中,如何避免数据被意外覆盖?EF Core乐观并发控制提供了一种优雅的解决方案。本文将手把手教你如何在C#项目中使用ConcurrencyToken特性来实现Entity Framework Core并发安全。

乐观并发控制(Optimistic Concurrency Control)是一种假设冲突很少发生的并发策略。它不会在读取数据时加锁,而是在更新数据时检查自上次读取以来数据是否被其他用户修改过。如果发现已被修改,则抛出异常,由开发者决定如何处理。
这与悲观并发控制(如数据库行锁)不同,后者在读取时就加锁,阻止其他用户访问,适用于高冲突场景,但会降低系统吞吐量。
想象这样一个场景:
如果没有并发控制,用户B的修改会直接覆盖用户A的更改,导致数据不一致。而通过C#并发处理中的乐观并发机制,系统可以在用户B保存时检测到冲突并提示用户。
EF Core 提供了多种方式实现乐观并发控制,最常用的是使用 [ConcurrencyCheck] 特性或 [Timestamp](也称为行版本)。我们这里重点介绍 [ConcurrencyCheck] 配合 ConcurrencyToken 的用法。
首先,在你的实体类中添加一个用于跟踪并发的属性,并标记为 [ConcurrencyCheck]。
using System.ComponentModel.DataAnnotations;public class Product{ public int Id { get; set; } public string Name { get; set; } = string.Empty; public decimal Price { get; set; } [ConcurrencyCheck] public DateTime LastModified { get; set; }}注意:LastModified 字段将作为并发令牌。每次更新记录时,你都需要手动更新这个字段(例如设置为 DateTime.UtcNow)。
你也可以在 OnModelCreating 中使用 Fluent API 来配置并发令牌:
protected override void OnModelCreating(ModelBuilder modelBuilder){ modelBuilder.Entity<Product>() .Property(p => p.LastModified) .IsConcurrencyToken();}这两种方式效果相同,你可以任选其一。
当你调用 SaveChanges() 时,如果检测到并发冲突,EF Core 会抛出 DbUpdateConcurrencyException。你需要捕获并处理它。
public async Task<bool> UpdateProductAsync(Product updatedProduct){ try { // 更新 LastModified 时间戳 updatedProduct.LastModified = DateTime.UtcNow; _context.Products.Update(updatedProduct); await _context.SaveChangesAsync(); return true; } catch (DbUpdateConcurrencyException ex) { // 并发冲突发生! foreach (var entry in ex.Entries) { var proposedValues = entry.CurrentValues; var databaseValues = entry.GetDatabaseValues(); if (databaseValues == null) { // 数据已被删除 continue; } // 可以选择: // 1. 重新加载最新数据并提示用户 // 2. 自动合并更改 // 3. 直接失败 // 示例:自动使用数据库最新值 entry.OriginalValues.SetValues(databaseValues); entry.Property(p => p.LastModified).CurrentValue = DateTime.UtcNow; } // 重试保存 await _context.SaveChangesAsync(); return false; // 表示发生了冲突 }}虽然上面的方法可行,但在SQL Server等数据库中,更高效的做法是使用 rowversion(或 timestamp)列。EF Core 对此有原生支持。
public class Product{ public int Id { get; set; } public string Name { get; set; } = string.Empty; public decimal Price { get; set; } [Timestamp] public byte[] RowVersion { get; set; } = null!;}使用 [Timestamp] 后,数据库会自动管理该字段,无需手动更新。EF Core 在更新时会自动将其加入 WHERE 条件,确保版本匹配。
通过本文,你已经掌握了如何在 C# 项目中使用 EF Core乐观并发控制 来防止数据覆盖问题。关键点包括:
[ConcurrencyCheck] 或 [Timestamp] 标记并发令牌字段DbUpdateConcurrencyException合理运用 Entity Framework Core并发机制,能显著提升你应用程序的数据一致性与用户体验。对于初学者来说,建议先从 [Timestamp] 开始尝试,它更简单且性能更好。
希望这篇关于 C#并发处理 的教程对你有所帮助!如有疑问,欢迎在评论区交流。
本文由主机测评网于2025-12-08发表在主机测评网_免费VPS_免费云服务器_免费独立服务器,如有疑问,请联系我们。
本文链接:https://vpshk.cn/2025124877.html