当前位置:首页 > C# > 正文

EF Core并发冲突处理详解(Entity Framework Core中实现乐观并发控制的完整教程)

在现代Web应用和企业级系统中,多个用户同时操作同一数据的情况非常普遍。如果不加以控制,就可能导致数据覆盖数据丢失的问题。这就是我们常说的并发冲突。本文将带你从零开始,深入浅出地掌握如何在EF Core(Entity Framework Core)中处理这类问题,即使是编程新手也能轻松上手!

什么是并发冲突?

假设你和同事同时编辑同一个客户信息:

  • 你修改了客户的电话号码
  • 同事修改了客户的邮箱地址
  • 你们几乎同时点击“保存”

如果没有并发控制机制,后保存的操作会直接覆盖前一个操作,导致一方的修改被悄悄丢弃——这就是典型的并发冲突。

EF Core并发冲突处理详解(Entity Framework Core中实现乐观并发控制的完整教程) Core并发控制 Entity Core并发冲突 乐观并发处理 .NET数据库并发 第1张

EF Core中的并发控制策略

EF Core 主要支持 乐观并发控制(Optimistic Concurrency),即默认允许多个用户同时读取和修改数据,但在提交时检查数据是否已被他人修改。如果检测到冲突,则抛出异常,由开发者决定如何处理。

1. 使用 RowVersion(时间戳)字段

这是最推荐的方式。在数据库表中添加一个 byte[] 类型的字段,并标记为 [Timestamp] 或使用 Fluent API 配置为并发令牌。

模型定义示例:

public class Customer{    public int Id { get; set; }    public string Name { get; set; } = string.Empty;    public string Email { get; set; } = string.Empty;    public string Phone { get; set; } = string.Empty;    [Timestamp]    public byte[]? RowVersion { get; set; }}

或者使用 Fluent API(在 DbContext 中配置):

protected override void OnModelCreating(ModelBuilder modelBuilder){    modelBuilder.Entity<Customer>()        .Property<byte[]>("RowVersion")        .IsRowVersion();}

2. 使用其他属性作为并发令牌

如果你不想用 RowVersion,也可以将任意属性(如 LastModified 时间)标记为并发令牌:

public class Product{    public int Id { get; set; }    public string Name { get; set; } = string.Empty;        [ConcurrencyCheck]    public DateTime LastModified { get; set; }}

如何捕获并处理并发异常?

当 EF Core 检测到并发冲突时,会抛出 DbUpdateConcurrencyException 异常。你需要在保存数据时捕获它,并决定如何响应。

基本处理示例:

try{    await _context.SaveChangesAsync();}catch (DbUpdateConcurrencyException ex){    foreach (var entry in ex.Entries)    {        var proposedValues = entry.CurrentValues;        var databaseValues = entry.GetDatabaseValues();        if (databaseValues == null)        {            // 数据已被删除            ModelState.AddModelError(string.Empty, "该记录已被其他用户删除。");        }        else        {            // 可选择:自动合并、提示用户、或重试            // 这里简单地将数据库值重新加载            entry.OriginalValues.SetValues(databaseValues);            entry.Property(nameof(Customer.RowVersion)).OriginalValue =                databaseValues.GetValue<byte[]>(nameof(Customer.RowVersion));            // 重新尝试保存(可选)            await _context.SaveChangesAsync();        }    }}

实战建议:用户友好型并发处理

在真实项目中,建议向用户展示冲突详情,让他们决定如何处理。例如:

  • 显示“您正在编辑的数据已被他人修改,请确认是否覆盖”
  • 提供“保留我的更改”、“使用最新数据”、“合并更改”等选项

这种交互方式能极大提升用户体验,避免数据意外丢失。

总结

通过本文,你已经掌握了在 EF Core 中处理并发冲突的核心方法:

  1. 使用 [Timestamp]IsRowVersion() 启用乐观并发
  2. 捕获 DbUpdateConcurrencyException 异常
  3. 根据业务需求选择自动重试、用户确认或数据合并策略

记住,良好的并发控制是构建可靠系统的基石。无论你是开发内部管理系统还是高并发的互联网应用,EF Core并发控制Entity Framework Core并发冲突乐观并发处理.NET数据库并发 都是你必须掌握的关键技能。

希望这篇教程对你有帮助!动手试试吧,实践是最好的老师。