ASP.NET Core 2.0 веб-API Entity Framework Core - в поисках более элегантного решения

Я работаю над проектом веб-API на ASP.NET Core 2.0 с подключением Entity Framework Core к базе данных postgres.

Следующий метод PUT работает без проблем, но я чувствую, что, возможно, неправильно понимаю использование метода update, и я также чувствую, что должно быть более элегантное решение для обновления существующего объекта способом, поддерживающим запрос 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);
        }
    }

Я чувствую, что должен быть лучший способ поместить новую информацию в базу данных, но у меня возникают проблемы с ее просмотром.

РЕДАКТИРОВАТЬ: Моя идея элегантного / лучшего было меньше кода для того же эффекта и лучшего использования инструментов, как справедливо предлагает Иван. Спасибо всем, кто предложил Automapper убрать утомительное переназначение переменных из dto в модель. Также большое спасибо Ивану Стоеву за объяснение работы принудительного обновления и частичного обновления, а также за идею, что лучше выполнять обработку ошибок с исключениями, а не с количеством затронутых строк.

1 ответ

Решение

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 может вернуться 0, поэтому вы не должны использовать его как показатель успеха. На самом деле, вы никогда не должны использовать его для этой цели, потому что EF сгенерирует исключение, если что-то пойдет не так.

Дополнительные сведения и примеры см. В разделе " Сохранение данных - отключенные объекты".

Другие вопросы по тегам