c# - 在带有 Entity Framework Core 的 ASP.NET Core WebAPI 的这个 PUT 方法中检查的目的是什么?
问题描述
我有一个带有 Entity Framework Core 的 ASP.NET Core WebAPI 应用程序。
我有以下模型类:
public class Item
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public long Id { get; set; }
[Required(ErrorMessage = "You must provide a name.")]
[MaxLength(255)]
public string Name { get; set; }
}
并搭建了一个“带有动作的API控制器,使用实体框架”,它具有以下方法:
[HttpPut("{id}")]
public async Task<IActionResult> PutItem(long id, Item item)
{
if (id != item.Id)
{
return BadRequest();
}
_context.Entry(item).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!ItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
我不明白if (id != item.Id)
支票。该Id
属性设置为是DatabaseGenerated
因为我希望它是我的主键,自动递增而不是由客户端提供,因此客户端可以只放置一个{"name":"item1"}
对象并成功。
那么为什么会有这个检查呢?是自动代码生成器的故障吗?我可以安全地删除它吗?
此外,如果 ID 不是数据库生成的,此检查是否可以确保用户传递的对象与他尝试更新的 ID 具有相同的 ID?
解决方案
该id
值来自 URL 路由:
[HttpPut("{id}")]
item.Id
价值来自发布的模型。人们可能认为两者兼有是多余的,但前者是标准 RESTful API 的一部分,而后者可能只是为了请求正文中模型的完整性。
这里的意图只是一个防御性编程检查,以确保两者相同。如果有人提交了两个不同的值,那么从语义上讲,它看起来像是试图修改记录的 ID,这当然不应该被允许。这只是针对此的健全性检查。
并且不是由客户提供
客户必须提供两者之一,以便您识别要更新的记录。如果需要,您通常可以忽略,item.Id
而只使用id
URL 路由中的值来识别记录。 但是,如果你这样做,那么你还需要做以下两件事之一:
item.Id = id;
在尝试将其附加到数据库上下文之前添加一行代码进行设置,或者- 与其将模型直接添加到数据库上下文中,不如将其
id
作为单独的对象获取记录并手动更新要更新的字段。
毕竟,如果item.Id
不是由客户端提供,那么它将默认为0
Entity Framework 将无法在没有Id
值的情况下直接附加该对象。上述选项将通过直接在对象上设置或在重新获取的对象上使用现有值来提供该值。
推荐阅读
- python - 全球信赖使单元测试成为不可能
- typescript - 如何折叠两种不同的类型?FP-TS
- angular - Angular/Typescript/RxJS - 如何向传入数组添加额外的项目
- python - 将图像粘贴到另一个图像上时,如何保持前景图像透明?
- python - 我可以在我导入的模块之前运行打印语句吗?
- c# - 点击当前页面链接时隐藏 Xamarin 中的菜单
- java - 读取文本文件以在 Java 中创建二维数组
- python - 仅解析没有名称的电子邮件地址
- sql - Oracle SQL中如何统计属于一个用户的银行账户数量
- mongodb - 输入'文件
' 不可分配给类型 'Pick