gpt4 book ai didi

asp.net-core - _context.SaveChanges() 有效但等待 _context.SaveChangesAsync() 无效

转载 作者:行者123 更新时间:2023-12-04 01:02:55 26 4
gpt4 key购买 nike

我正在努力理解一些东西。我有一个 .Net Core 2.2 Web API,带有 MySQL 8 数据库,并使用 Pomelo 库连接到 MySQL 服务器。

我有一个看起来像这样的 PUT 操作方法:

// PUT: api/Persons/5
[HttpPut("{id}")]
public async Task<IActionResult> PutPerson([FromRoute] int id, Person person)
{
if (id != person.Id)
{
return BadRequest();
}

_context.Entry(person).State = EntityState.Modified;

try
{
_context.SaveChanges(); // Works
// await _context.SaveChangesAsync(); // Doesn't work
}
catch (DbUpdateConcurrencyException)
{
if (!PersonExists(id))
{
return NotFound();
}
else
{
throw;
}
}

return NoContent();
}

根据我在上面代码片段中的评论,当我调用 _context.SaveChanges() 时,它可以工作(即它更新 MySQL 数据库中的相关记录,并返回 1)但是当我调用 await _context.SaveChangesAsync() 时,它不起作用(它不更新记录,并返回 0)。它没有抛出异常或任何东西 - 它只是不更新​​记录。

有任何想法吗?

最佳答案

正如我在上面的评论中所说,EF Core 没有真正的同步方法。同步方法(例如 SaveChanges )仅阻塞异步方法(例如 SaveChangesAsync )。因此,SaveChanges 是不可能的。会起作用,如果 SaveChangesAsync不会,因为前者只是后者的代理。这里还有一些其他问题在起作用,从您提供的代码中看不出来。

然而,我写这个作为答案的原因是你这样做的方式通常是错误的,我相信如果做得对,问题可能会消失。您永远不应该,我的意思是永远不要将从请求正文创建的实例直接保存到您的数据库中。这提供了一种攻击媒介,允许恶意用户以不良方式更改您的数据库。您已经通过检查 id 没有被修改来部分解决这一问题,但用户仍然可以更改他们不应该被允许的内容。

撇开安全漏洞不谈,不这样做是有实际原因的。 API 用作反腐败层,但前提是您将实体与客户端交互的对象分离。当您直接使用实体时,您将数据库与 API 层紧密耦合,因此数据库级别的任何更改都需要 API 的新版本,更糟糕的是,没有机会弃用以前的版本。所有客户端必须立即更新,否则他们的实现将中断。通过向客户端公开 DTO 类,数据库可以独立于 API 发展,因为您可以添加任何必要的反腐败逻辑来弥合两者之间的差距。

总而言之,这就是您的方法应该如何构建:

// PUT: api/Persons/5
[HttpPut("{id}")]
public async Task<IActionResult> PutPerson([FromRoute] int id, PersonModel model)
{
// not necessary if using `[ApiController]`
if (!ModelState.IsValid)
return BadRequest();

var person = await _context.People.FindAsync(id);
if (person == null)
return NotFound();

// map `model` onto `person`

try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
// use an optimistic concurrency strategy from:
// https://docs.microsoft.com/en-us/ef/core/saving/concurrency#resolving-concurrency-conflicts
}

return NoContent();
}

我想保持代码直截了当,但是为了处理乐观并发,我实际上建议使用 Polly 异常处理库。您可以设置重试策略,该策略可以在纠错后继续尝试进行更新。否则,您需要在 try/catch 中的 try/catch 中进行 try/catch 等。此外, DbUpdateConcurrencyException是您应该始终以某种方式处理的事情,因此重新抛出它是没有意义的。

关于asp.net-core - _context.SaveChanges() 有效但等待 _context.SaveChangesAsync() 无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57854317/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com