Как управлять параллелизмом данных в контексте объекта (платформа Entity Framework)
В этом разделе приведен пример того, как управлять параллелизмом в контексте объекта. В данном разделе рассматриваются формирование и обработка исключения OptimisticConcurrencyException при обновлении свойства Status объекта SalesOrderHeader. Дополнительные сведения см. в разделе Сохранение изменений и управление параллелизмом (платформа Entity Framework).
Пример в этом разделе основан на модели Adventure Works Sales. Чтобы запустить код из данного примера, нужно сначала добавить к проекту модель AdventureWorks Sales и настроить его для использования платформы Entity Framework. Для этого выполните инструкции из разделов Как вручную настроить проект Entity Framework и Как определить модель и файлы сопоставления вручную (платформа Entity Framework).
Чтобы успешно сформировать исключение OptimisticConcurrencyException, необходимо изменить свойство Status в файле концептуального сопоставления.
Включение проверки параллелизма применительно к свойству Status
Откройте файл AdventureWorks.csdl и найдите определение для сущности SalesOrderHeader.
Найдите дочерний элемент Status и добавьте следующий атрибут:
ConcurrencyMode="fixed"
Сохраните изменения в файле AdventureWorks.csdl.
В следующем примере кода задайте точку останова после цикла foreach (For Each в Visual Basic) и запустите приложение в режиме отладки.
После того как произойдет останов выполнения, воспользуйтесь средой SQL Server Management Studio для выполнения следующей команды Transact-SQL применительно к базе данных AdventureWorks:
UPDATE Sales.SalesOrderHeader SET Status = 1 WHERE CreditCardApprovalCode IS NULL.
Возобновите выполнение программы.
Пример
В этом примере изменения в свойстве Status объекта SalesOrderHeader вызывают исключение OptimisticConcurrencyException при условии соблюдения описанной выше процедуры.
Using context As New AdventureWorksEntities()
Try
' Perform an operation with a high-level of concurrency.
' Change the status of all orders without an approval code.
Dim orders As ObjectQuery(Of SalesOrderHeader) = context.SalesOrderHeaders.Where("it.CreditCardApprovalCode IS NULL").Top("100")
For Each order As SalesOrderHeader In orders
' Reset the order status to 4 = Rejected.
order.Status = 4
Next
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
For Each order As SalesOrderHeader In orders
Console.WriteLine(("Order ID: " & order.SalesOrderID.ToString() & " Order status: ") + order.Status.ToString())
Next
Catch ex As UpdateException
Console.WriteLine(ex.ToString())
End Try
End Using
using (AdventureWorksEntities context =
new AdventureWorksEntities())
{
try
{
// Perform an operation with a high-level of concurrency.
// Change the status of all orders without an approval code.
ObjectQuery<SalesOrderHeader> orders =
context.SalesOrderHeaders.Where(
"it.CreditCardApprovalCode IS NULL").Top("100");
foreach (SalesOrderHeader order in orders)
{
// Reset the order status to 4 = Rejected.
order.Status = 4;
}
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");
}
foreach (SalesOrderHeader order in orders)
{
Console.WriteLine("Order ID: " + order.SalesOrderID.ToString()
+ " Order status: " + order.Status.ToString());
}
}
catch (UpdateException ex)
{
Console.WriteLine(ex.ToString());
}
}