ASP.NET Web API - 用于更新实体的线程安全逻辑

Nik*_*sel 6 c# asp.net multithreading entity-framework asp.net-web-api

我有以下方法Item为某些用户添加或更新类型的实体.此方法是Service类的一部分,为每个请求创建一个新实例.

public async Task SaveItem(int userId, string name)
{
    var item = await _context.Items.Where(i => i.UserId == userId).SingleOrDefaultAsync();

    if (item == null)
    {
        item = new Item
        {
            UserId = userId,
            Name = name
        };
        _context.Items.Add(item);
    }
    else
    {
        item.Name = name;
        _context.Entry(item).State = System.Data.Entity.EntityState.Modified;
    }

    await _context.SaveChangesAsync();
}
Run Code Online (Sandbox Code Playgroud)

问题是两个并发请求可能为同一用户创建两个无效的项目.对我来说,它看起来像一个非常常见的代码片段,我想知道处理这种并发问题的默认方式是什么.

Sam*_*ath 4

您必须Concurrency Conflicts妥善处理您的申请。

1.悲观并发(锁定)

如果您的应用程序确实需要防止并发场景中的意外数据丢失,一种方法是使用数据库锁。这称为悲观并发。例如,在从数据库读取行之前,您请求锁定以进行只读或更新访问。如果您锁定某行以进行更新访问,则其他用户将无法锁定该行以进行只读或更新访问,因为他们将获得正在更改的数据的副本。如果您锁定某行以进行只读访问,其他人也可以锁定该行以进行只读访问,但不能进行更新。

2.乐观并发

悲观并发的替代方案是乐观并发。乐观并发意味着允许并发冲突发生,然后在发生冲突时做出适当反应。

请阅读使用实体框架处理并发一文以获取更多信息。