Поделиться через


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

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

Пример в этом разделе основан на модели Adventure Works Sales. Чтобы запустить код, используемый в данном примере, нужно сначала добавить к проекту модель AdventureWorks Sales и настроить его для использования платформы Entity Framework. Для этого выполните инструкции из разделов Как вручную настроить проект Entity Framework и Как определить модель EDM вручную (платформа 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.SalesOrderHeader.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 ex 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.SalesOrderHeader.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)
Работа с объектами (задачи Entity Framework)