Сохранение изменений и управление параллелизмом (платформа 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)