首页 > 解决方案 > 异步合理性检查会导致出现竞争条件吗?

问题描述

我有一个使用 EF Core 的 .Net 5 Web API 项目,并考虑了我的业务处理程序的数据一致性。我个人认为这个问题与技术无关,也适用于其他 Web 框架。以下只是一个例子(设计可能不好)

想象一下 API 提供了两个端点

数据库持有一个交叉表

用户 文档
用户 1 文件1
用户 1 文档2
用户 2 文档2

将用户链接到文档的逻辑可能看起来像

var user = await FetchUserFromDb(userId);

if(user == null) 
{
    return new NotFoundResponse($"user {userId} not found");
}

var document = await FetchDocumentFromDb(documentId);

if(document == null) 
{
    return new NotFoundResponse($"document {documentId} not found");
}

var insertResult = await InsertIntoCrossTable(userId, documentId);

return new CreatedResponse(insertResult);

删除用户的逻辑可能看起来像

var affectedRows = await DeleteUserFromDb(userId);

if(affectedRows == 0) 
{
    return new NotFoundResponse($"user {userId} not found");
}

return new NoContentResponse("user deleted successfully");

目前,我不知道如果两个请求同时进来会发生什么。POST 请求将成功返回用户,然后尝试从数据库中检索文档。如果此时用户被删除,POST 请求中的业务逻辑将不再意识到这一点。插入查询语句将引发数据库异常,因为用户的外键不再存在。

我在这里错了吗,请求一个接一个地处理?还是我作为开发人员必须专门处理这个问题(通过为数据库异常添加额外的 try/catch 语句)?

标签: c#entity-framework-coreasp.net-core-webapirace-condition

解决方案


Or do I as a developer have to deal with this issue specifically (by adding additional try/catch statements for database exceptions)?

You do have to deal with it some way. Either:

  1. Extend your transaction to include both the select and the insert, or
  2. Handle the exception (either with retries that will also retry the select or returning an error code), or
  3. Don't handle the exception and let the user/UI refresh on error.

what if my data source is not a database?

That's an impossibly broad question. So the answer is also broad: "use whatever concurrency techniques are recommended for your data source."


推荐阅读