ASP.NET Core 2.0 web api Entity Framework Core - 寻找更优雅的解决方案
ASP.NET Core 2.0 web api Entity Framework Core - looking for a more elegant solution
我正在 ASP.NET Core 2.0 上的 Web api 项目上工作,Entity Framework Core 连接到 postgres 数据库。
下面的 PUT 方法没有问题,但我觉得我可能误解了更新方法的使用,我也觉得应该有一个更优雅的解决方案来以 PUT 持有的方式更新现有对象请求(不是 PATCH)。
// PUT: api/Discount/5
[HttpPut("{id}")]
[ProducesResponseType(204)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public IActionResult Put(int id, [FromBody]Discount discount)
{
if (ModelState.IsValid)
{
using (var context = new BarberskabetDbContext())
{
if (context.Discounts.Any(x => x.DiscountId == id && !x.Deleted))
{
var dbDiscount = context.Discounts.FirstOrDefault(x => x.DiscountId == id && !x.Deleted);
dbDiscount.AppliesOnce = discount.AppliesOnce;
dbDiscount.AppliesToProductType = discount.AppliesToProductType;
dbDiscount.Code = discount.Code;
dbDiscount.DiscountType = discount.DiscountType;
dbDiscount.Duration = discount.Duration;
dbDiscount.DurationUsageLimit = discount.DurationUsageLimit;
dbDiscount.EndsAt = discount.EndsAt;
dbDiscount.OncePerCustomer = discount.OncePerCustomer;
dbDiscount.RestrictByEmail = discount.RestrictByEmail;
dbDiscount.StartsAt = discount.StartsAt;
dbDiscount.Status = discount.Status;
dbDiscount.TimesUsed = discount.TimesUsed;
dbDiscount.UsageLimit = discount.UsageLimit;
dbDiscount.Value = discount.Value;
context.Update(dbDiscount);
if (context.SaveChanges() == 0)
{
return StatusCode(500, "Unable to update record.");
}
return NoContent();
}
else
{
return NotFound();
}
}
}
else
{
return BadRequest(ModelState);
}
}
我觉得应该有更好的方法将新信息放入数据库,但我无法看到它。
编辑:
正如 Ivan 正确建议的那样,我对 elegant/better 的想法是减少相同效果的代码和更好地使用工具。
感谢所有建议 Automapper 删除变量从 dto 到模型的繁琐重新映射的人。还要特别感谢 Ivan Stoev,他解释了强制更新和部分更新的工作原理,以及最好使用异常而不是受影响的行数进行错误处理的想法。
Update
方法用于所谓的 强制更新 ,即当您断开了您确定存在的实体时。它无需从数据库加载实体即可工作,只需更新所有属性即可。
以您的示例为例,强制更新如下所示:
if (context.Discounts.Any(x => x.DiscountId == id && !x.Deleted))
{
context.Update(discount);
context.SaveChanges();
}
如果您只想更新已更改的属性(如果有),则应加载数据库实体并使用 CurrentValues.UpdateValues
方法应用更改:
var dbDiscount = context.Discounts.FirstOrDefault(x => x.DiscountId == id && !x.Deleted);
if (dbDiscount != null)
{
context.Entry(dbDiscount).CurrentValues.SetValues(discount);
context.SaveChanges();
}
请注意,在这种情况下,EF 可能根本不会发出更新命令(如果所有 属性 值都与原始值相同),即 SaveChanges
可以 return 0
,所以你不应该用它作为成功的标志。事实上,你永远不应该将它用于该目的,因为如果出现问题,EF 会抛出异常。
有关详细信息和示例,请参阅 Saving Data - Disconnected Entities 文档主题。
我正在 ASP.NET Core 2.0 上的 Web api 项目上工作,Entity Framework Core 连接到 postgres 数据库。
下面的 PUT 方法没有问题,但我觉得我可能误解了更新方法的使用,我也觉得应该有一个更优雅的解决方案来以 PUT 持有的方式更新现有对象请求(不是 PATCH)。
// PUT: api/Discount/5
[HttpPut("{id}")]
[ProducesResponseType(204)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
[ProducesResponseType(500)]
public IActionResult Put(int id, [FromBody]Discount discount)
{
if (ModelState.IsValid)
{
using (var context = new BarberskabetDbContext())
{
if (context.Discounts.Any(x => x.DiscountId == id && !x.Deleted))
{
var dbDiscount = context.Discounts.FirstOrDefault(x => x.DiscountId == id && !x.Deleted);
dbDiscount.AppliesOnce = discount.AppliesOnce;
dbDiscount.AppliesToProductType = discount.AppliesToProductType;
dbDiscount.Code = discount.Code;
dbDiscount.DiscountType = discount.DiscountType;
dbDiscount.Duration = discount.Duration;
dbDiscount.DurationUsageLimit = discount.DurationUsageLimit;
dbDiscount.EndsAt = discount.EndsAt;
dbDiscount.OncePerCustomer = discount.OncePerCustomer;
dbDiscount.RestrictByEmail = discount.RestrictByEmail;
dbDiscount.StartsAt = discount.StartsAt;
dbDiscount.Status = discount.Status;
dbDiscount.TimesUsed = discount.TimesUsed;
dbDiscount.UsageLimit = discount.UsageLimit;
dbDiscount.Value = discount.Value;
context.Update(dbDiscount);
if (context.SaveChanges() == 0)
{
return StatusCode(500, "Unable to update record.");
}
return NoContent();
}
else
{
return NotFound();
}
}
}
else
{
return BadRequest(ModelState);
}
}
我觉得应该有更好的方法将新信息放入数据库,但我无法看到它。
编辑: 正如 Ivan 正确建议的那样,我对 elegant/better 的想法是减少相同效果的代码和更好地使用工具。 感谢所有建议 Automapper 删除变量从 dto 到模型的繁琐重新映射的人。还要特别感谢 Ivan Stoev,他解释了强制更新和部分更新的工作原理,以及最好使用异常而不是受影响的行数进行错误处理的想法。
Update
方法用于所谓的 强制更新 ,即当您断开了您确定存在的实体时。它无需从数据库加载实体即可工作,只需更新所有属性即可。
以您的示例为例,强制更新如下所示:
if (context.Discounts.Any(x => x.DiscountId == id && !x.Deleted))
{
context.Update(discount);
context.SaveChanges();
}
如果您只想更新已更改的属性(如果有),则应加载数据库实体并使用 CurrentValues.UpdateValues
方法应用更改:
var dbDiscount = context.Discounts.FirstOrDefault(x => x.DiscountId == id && !x.Deleted);
if (dbDiscount != null)
{
context.Entry(dbDiscount).CurrentValues.SetValues(discount);
context.SaveChanges();
}
请注意,在这种情况下,EF 可能根本不会发出更新命令(如果所有 属性 值都与原始值相同),即 SaveChanges
可以 return 0
,所以你不应该用它作为成功的标志。事实上,你永远不应该将它用于该目的,因为如果出现问题,EF 会抛出异常。
有关详细信息和示例,请参阅 Saving Data - Disconnected Entities 文档主题。