Как вы используете оптимистичный параллелизм с контроллером OAPA WebAPI

asp.net asp.net-web-api asp.net-web-api-odata entity-framework-6 odata

Вопрос

У меня есть контроллер WebAPI OData, который использует Delta для частичного обновления моего объекта.

В моей модели структуры сущности у меня есть поле Version. Это rowversion в базе данных SQL Server и сопоставляется с массивом байтов в Entity Framework с режимом параллелизма, установленным в Fixed (сначала используется база данных).

Я использую fiddler для отправки частичного обновления с использованием устаревшего значения для поля Version. Я загружаю текущую запись из своего контекста, а затем я исправляю мои измененные поля сверху, что изменяет значения в столбце «Версия», не вызывая ошибки, а затем, когда я сохраняю изменения в моем контексте, все сохраняется без ошибок. Очевидно, что ожидается, что объект, который сохраняется, не был удален из контекста, так как я могу реализовать оптимистичный параллелизм с Delta.

Я использую самые последние версии всего (или был перед рождеством), поэтому Entity Framework 6.0.1 и OData 5.6.0

public IHttpActionResult Put([FromODataUri]int key, [FromBody]Delta<Job> delta)
{
    using (var tran = new TransactionScope())
    {
        Job j = this._context.Jobs.SingleOrDefault(x => x.JobId == key);

        delta.Patch(j);

        this._context.SaveChanges();

        tran.Complete();

        return Ok(j);
    }
}

благодаря

Популярные ответы

Я просто столкнулся с этим, используя контроллеры Entity Framework 6 и Web API 2 OData.

EF DbContext, похоже, использует исходное значение метки времени, полученной, когда объект был загружен в начале методов PUT / PATCH для проверки параллелизма при последующем обновлении.

Обновление текущего значения метки времени до значения, отличного от значения в базе данных перед сохранением изменений, не приводит к ошибке параллелизма.

Я обнаружил, что вы можете «исправить» это поведение, заставив исходное значение метки времени быть текущим в контексте.

Например, вы можете сделать это, переопределив SaveChanges в контексте, например:

public partial class DataContext
{
    public override int SaveChanges()
    {
        foreach (DbEntityEntry<Job> entry in ChangeTracker.Entries<Job>().Where(u => u.State == EntityState.Modified))
            entry.Property("Timestamp").OriginalValue = entry.Property("Timestamp").CurrentValue;

        return base.SaveChanges();
    }
}

(Предполагая, что столбец параллелизма называется «Временная метка», а режим параллелизма для этого столбца установлен в «Исправлено» в EDMX)

Дальнейшим усовершенствованием этого было бы написать и применить пользовательский интерфейс ко всем вашим моделям, требующим этого исправления, и просто заменить «Job» интерфейсом в приведенном выше коде.

Обратная связь от Rowan в группе Entity Framework (4 августа 2015 г.):

Это по дизайну. В некоторых случаях вполне корректно обновлять токен параллелизма, и в этом случае нам нужно текущее значение для хранения значения, которое должно быть установлено, и исходного значения, которое должно содержать значение, которое мы должны проверить. Например, вы можете настроить Person.LastName как токен параллелизма. Это один из недостатков шаблона «запрос и обновление», который используется в этом действии.

Логика, которую вы добавили для установки правильного исходного значения, - это правильный подход к использованию в этом сценарии.




Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему