EF Core 3 для обновления одного столбца вместо полной строки - PullRequest
0 голосов
/ 26 марта 2020

Ищу способ обновления одного столбца в одной строке таблицы с помощью EF Core 3. Вот мой сценарий, который я ищу. Сегодня у меня есть класс, определенный следующим образом:

public partial class Records
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public int UserId { get; set; }
    public string UserText { get; set; }
    public DateTime? UserDate { get; set; }
    public bool? NotificationSent { get; set; }
}

И у меня есть такая команда PUT:

[HttpPut("{customerId}/{id}")]
    public async Task<IActionResult> PutRecords([FromHeader(Name = "Token")] string token, [FromHeader(Name = "Secret")] string secret, int id, Records record)
    {
        if (id != record.Id)
        {
            return BadRequest();
        }

        _context.Entry(record).State = EntityState.Modified;

        try
        {
            await _context.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!RecordsExists(id))
            {
                return NotFound();
}
            else
            {
                throw;
            }
        }
        return Ok("Success"); ;
    }

Когда я отправляю свой клиент, я надеялся, что смогу просто отправить в идентификаторе и одном столбце, например:

{
"Id": 140225,
"UserText": "Test"

}

И тогда будет обновляться только этот единственный текст. Но происходит то, что передаваемое значение «запись» содержит имена каждого объекта в классе, значение которого равно нулю или 0, а затем обновляет все столбцы в этой строке этими значениями.

Я провел какое-то исследование, и я знаю, что могу использовать что-то вроде:

var Record = await _context.Records.FindAsync(id);
        Record.UserText = record.UserText;
        _context.Entry(Record).Property("UserText").IsModified = true;

, и тогда он обновляет только этот единственный столбец. Похоже, я не могу понять, как добраться от А до Б со знаниями, которые я изложил. Просто любопытно, сталкивался ли кто-нибудь еще с этим или имеет крутое решение. Возможно, я прошёл через запись oop, пытаясь найти значения, чтобы можно было установить IsModified, но мне не повезло, чтобы это работало правильно.

1 Ответ

1 голос
/ 26 марта 2020

Это ожидаемое поведение при передаче объектов между клиентом и сервером. Лучший подход, если вы хотите обновить значения, это загрузить объект в запросе, установить соответствующие значения (после проверки) и затем сохранить изменения.

Когда отслеживаемый объект обновляется, он генерирует соответствующее обновление. операторы только для изменяющихся столбцов.

Например, чтобы обновить описание сущности:

[HttpPut("{customerId}/{id}")]
public async Task<IActionResult> UpdateDescription([FromHeader(Name = "Token")] string token, [FromHeader(Name = "Secret")] string secret, int id, string description, int rowVersion)
{
    var record = _context.Records.Single(x => x.Id == id);
    // TODO: Check the user associated to this session/request and assert they have permissions to this record.

    if (rowVersion != record.RowVersion)
    {
        // Consider Refusing the update, notify user that data has changed & refresh.
    }

    record.Description = description;
    _context.SaveChanges();
}

Это не обязательно должно быть так же определено c, как у этого (1 поле) это может быть обновление через модель представления разрешенных полей, которые можно изменить, которые вы можете проверить и скопировать по отдельности или использовать Automapper для сопоставления с загруженной сущностью. Однако, как правило, предпринимаемые действия должны быть как можно более точными c, принимая только те данные, которые необходимы для определения того, что обновлять, и значения, подлежащие обновлению. Определенно, не вся сущность, поскольку подделка может привести к обновлению значений, которые никогда не должны изменяться, или изменять их способами, которые не предназначены.

Этот подход помогает избежать устаревших изменений данных, проверяя версию строки или последнее изменение отметка времени, et c. Он также должен проверять текущий сеанс пользователя по извлеченным строкам, чтобы убедиться, что предоставленный идентификатор может быть проверен. Например, передавать ID и отсоединенную сущность, а затем проверять id == model.Id бессмысленно. Фальсификация может быть выполнена обоими значениями клиентом или человеком в середине.

...