EF Core和ASP.NET Core中处理并发的最佳实践是什么?

5

当我插入/更新实体时,我目前正在执行以下操作:

public async Task<IdentityResult> UpdateAsync(Model model, CancellationToken ct = default)
{
    var entity = await GetAsync(ct);
    if (entity == null)
    {
        return await CreateAsync(model, ct);
    }
    context.Entry(entity).State = EntityState.Detached;

    Update(model);
    model.ConcurrencyToken = Guid.NewGuid().ToString();

    await context.SaveChangesAsync();
    return IdentityResult.Success;
}

更新方法如下:

protected virtual T Update(T entity)
{
    var dbEntityEntry = context.Entry(entity);
    if (dbEntityEntry.State == EntityState.Detached)
    {
        dbSet.Attach(entity);
        dbEntityEntry.State = EntityState.Modified;
    }

    return entity;
}

这个可以工作,但是是否有更好(通用)的处理并发的方法?

1个回答

11

是的,EF Core 有一种通用的处理并发的方法。您已经完成了第一步,通过添加一个列来管理每次更新的行版本,但是您手动更新了并发标记。

最好的方法是使用 Timestamp 让数据库自动更新并发标记,如在EF Core文档中解释的那样:

时间戳/行版本是一种属性,每次插入或更新行时,数据库会自动生成一个新值。该属性也被视为并发标记,确保在查询它以后,如果正在更新的行已更改,则会引发异常。具体细节取决于所使用的数据库提供程序; 对于 SQL Server,通常使用 byte[] 属性,并将其设置为数据库中的 ROWVERSION 列。

如何使用它 (源自 EF Core 文档):

public class Blog
{
    public int BlogId { get; set; }

    public string Url { get; set; }

    [Timestamp]
    public byte[] Timestamp { get; set; }
}

所以不需要更新Timestamp或者ConcurrencyCheck列,因为数据库会自动为您完成。

最后一部分是确保正确处理并发冲突,并让用户知道他/她已过时。如何管理并发冲突(它们会引发异常)。您可以按照这里所述的内容进行操作。

还请检查此教程


3
新属性是[ConcurrencyCheck]。https://learn.microsoft.com/zh-cn/ef/core/modeling/concurrency?tabs=data-annotations - Jess
我只是在说,在 .NET Core 中,ConcurrencyToken 似乎已经被重命名为 ConcurrencyCheck。 - Jess
1
“ConcurrencyCheck”和“TimeStamp”并不是同一件事情。“TimeStamp”在数据库中具有本地支持,而“ConcurrencyCheck”必须在应用程序中手动更新。 - Codingwiz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接