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

В этом разделе приведен пример того, как управлять параллелизмом в контексте объекта. В данном разделе рассматриваются формирование и обработка исключения OptimisticConcurrencyException при обновлении свойства Status объекта SalesOrderHeader. Дополнительные сведения см. в разделе Сохранение изменений и управление параллелизмом (платформа Entity Framework).

Пример в этом разделе основан на модели Adventure Works Sales. Чтобы запустить код из данного примера, нужно сначала добавить к проекту модель AdventureWorks Sales и настроить его для использования платформы Entity Framework. Для этого выполните инструкции из разделов Как вручную настроить проект Entity Framework и Как определить модель и файлы сопоставления вручную (платформа Entity Framework).

Чтобы успешно сформировать исключение OptimisticConcurrencyException, необходимо изменить свойство Status в файле концептуального сопоставления.

Включение проверки параллелизма применительно к свойству Status

  1. Откройте файл AdventureWorks.csdl и найдите определение для сущности SalesOrderHeader.

  2. Найдите дочерний элемент Status и добавьте следующий атрибут:

    ConcurrencyMode="fixed"
    
  3. Сохраните изменения в файле AdventureWorks.csdl.

  4. В следующем примере кода задайте точку останова после цикла foreach (For Each в Visual Basic) и запустите приложение в режиме отладки.

  5. После того как произойдет останов выполнения, воспользуйтесь средой SQL Server Management Studio для выполнения следующей команды Transact-SQL применительно к базе данных AdventureWorks:

    UPDATE Sales.SalesOrderHeader SET Status = 1 WHERE CreditCardApprovalCode IS NULL.
    
  6. Возобновите выполнение программы.

Пример

В этом примере изменения в свойстве 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());
    }
}

См. также

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

Работа с объектами (платформа Entity Framework)