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 文档主题。