Сохранение изменений и управление параллелизмом (платформа Entity Framework)

По умолчанию в платформе Entity Framework реализуется модель оптимистичного параллелизма. Это означает, что между процессами запроса данных и обновления данных блокировки данных в источнике данных не удерживаются. Entity Framework сохраняет сделанные в объекте изменения в базе данных, не проверяя их на параллелизм. Для сущностей, которые могут обладать высокой степенью параллелизма, рекомендуется, чтобы сущность определяла свойство на концептуальном уровне посредством атрибута ConcurrencyMode="fixed", как показано в следующем примере.

<Property Name="Status" Type="Byte" Nullable="false" ConcurrencyMode="Fixed" />

При использовании этого атрибута Entity Framework проверяет изменения в базе данных, прежде чем их сохранить. Любое конфликтующее изменение вызывает исключение OptimisticConcurrencyException. Дополнительные сведения см. в разделе Как управлять параллелизмом данных в контексте объекта (платформа Entity Framework). OptimisticConcurrencyException может также возникнуть при определении модель EDM (сущностная модель данных) , который использует хранимые процедуры для обновления источника данных. В этом случае исключение возникает, когда хранимая процедура, используемая для обновления отчетов, сообщает об обновлении нулевого количества строк.

При обновлениях в таких сценариях с высокой степенью параллелизма рекомендуется чаще вызывать метод Refresh. При вызове метода Refresh режим обновления RefreshMode управляет передачей изменений. При наличии параметра StoreWins Entity Framework перезаписывает все данные в кэше объектов соответствующими значениями из базы данных. И наоборот, параметр ClientWins замещает исходные значения в кэше последними значениями из источника данных. Это обеспечивает успешное сохранение в источнике данных всех измененных данных в кэше объектов, устраняя конфликты между изменениями данных в кэше и изменениями тех же данных в источнике данных.

Вызовите метод Refresh после вызова метода SaveChanges, если обновление источника данных может изменить данные, принадлежащие другим объектам в контексте объекта. Например, добавление нового объекта SalesOrderDetail в модели AdventureWorks Sales запускается обновление столбца подытогов, чтобы новый элемент был включен в подытог. В данном случае вызовите метод Refresh и передайте объект SalesOrderHeader для заказа. Это обеспечит отправку значений, сформированных триггером, в объект SalesOrderHeader в контексте объекта.

Entity Framework отслеживает изменения объектов в кэше. При вызове метода SaveChanges Entity Framework пытается выполнить слияние изменений в источнике данных. SaveChanges может завершиться с ошибкой OptimisticConcurrencyException, если изменения данных в кэше объектов конфликтуют с изменениями, произведенными в источнике данных после добавления объектов или обновления кэша. Это приводит к откату всей транзакции. Если возникает исключение OptimisticConcurrencyException, необходимо обработать его, вызвав метод Refresh и указав, должен ли конфликт разрешаться сохранением данных в данных объекта (ClientWins) или обновлением кэша объекта данными из источника данных (StoreWins), как в следующем примере.

Try
    ' Try to save changes, which may cause a conflict. 
    Dim num As Integer = context.SaveChanges()
    Console.WriteLine("No conflicts. " & num.ToString() & " updates saved.")
Catch generatedExceptionName As OptimisticConcurrencyException
    ' Resolve the concurrency conflict by refreshing the 
    ' object context before re-saving changes. 
    context.Refresh(RefreshMode.ClientWins, orders)

    ' Save changes. 
    context.SaveChanges()
    Console.WriteLine("OptimisticConcurrencyException handled and changes saved")
End Try
try
{
    // Try to save changes, which may cause a conflict.
    int num = context.SaveChanges();
    Console.WriteLine("No conflicts. " +
        num.ToString() + " updates saved.");
}
catch (OptimisticConcurrencyException)
{
    // Resolve the concurrency conflict by refreshing the 
    // object context before re-saving changes. 
    context.Refresh(RefreshMode.ClientWins, orders);

    // Save changes.
    context.SaveChanges();
    Console.WriteLine("OptimisticConcurrencyException "
    + "handled and changes saved");
}

SaveChanges может создавать UpdateException, если объект, добавленный к ObjectContext, невозможно создать в источнике данных. Это может произойти, если строка с внешним ключом, указанным связью, уже существует. В этом случае нельзя использовать Refresh при обновлении добавленного объекта в контексте объекта. Вместо этого повторно загрузите объект со значением OverwriteChanges для MergeOption.

Дополнительные сведения об управлении контекстом объекта см. в разделе Как управлять параллелизмом данных в контексте объекта (платформа Entity Framework).

В качестве альтернативы оптимистичному параллелизму можно использовать транзакции. Дополнительные сведения см. в разделе Управление соединениями и транзакциями (платформа Entity Framework).

В этом разделе

Как управлять параллелизмом данных в контексте объекта (платформа Entity Framework)

См. также

Основные понятия

Работа с объектами (платформа Entity Framework)
Создание, добавление, изменение и удаление объектов (платформа Entity Framework)