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 сгенерирует исключение, если что-то пойдет не так.
Дополнительные сведения и примеры см. В разделе " Сохранение данных - отключенные объекты".