此 PUT 方法中此检查的目的是什么,该方法使用实体框架核心 ASP.NET 核心 WebAPI?



我有一个带有实体框架核心的 ASP.NET 核心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值来自 URL 路由:

[HttpPut("{id}")]

item.Id值来自发布的模型。 人们可能认为两者兼而有之是多余的,但前者是标准 RESTful API 的一部分,后者可能只是为了请求正文中模型的完整性。

这里的意图只是一个防御性编程检查,以确保两者相同。 如果有人提交了两个不同的值,那么从语义上讲,它看起来像是试图修改记录的 ID,这当然是不允许的。 这只是对此的健全性检查。

而不是由客户提供

客户端必须提供两者之一,以便您识别要更新的记录。 如果需要,通常可以忽略item.Id,只需使用 URL 路由中的id值来标识记录。但是,如果您这样做,那么您还需要执行以下两项操作之一:

  1. 在尝试将item.Id = id;附加到数据库上下文之前,添加一行代码以设置,或者
  2. 不要将模型直接添加到数据库上下文中,而是按记录id作为单独的对象获取记录,并手动更新要更新的字段。

毕竟,如果客户端未提供item.Id,则它将默认为0,并且实体框架将无法在没有Id值的情况下直接附加该对象。 上述选项将通过直接在对象上设置该值或在重新获取的对象上使用现有值来提供该值。

POST 通常用于创建对象。 PUT通常用于更新。 要更新它,您需要知道它的身份。 最有可能long id是 URL 或查询字符串的一部分。Item item来自身体。 该检查可确保正文中提供的实体与 URL 指定的实体匹配。

最新更新