如何:在对象上下文中管理数据并发性(实体框架)

本主题提供如何在对象上下文中管理并发性的示例。 在本主题中,您将在更新 SalesOrderHeader 对象的 Status 属性时生成和处理 OptimisticConcurrencyException。 有关更多信息,请参见保存更改和管理并发(实体框架)

本主题中的示例基于 Adventure Works 销售模型。 若要运行本示例中的代码,必须已将 AdventureWorks 销售模型添加到您的项目中,并将项目配置为使用实体框架。 为此,请完成如何:手动配置实体框架项目如何:手动定义模型和映射文件(实体框架) 中的过程。

为了成功地生成 OptimisticConcurrencyException,必须在概念映射文件中修改 Status 属性。

对 Status 属性启用并发检查

  1. 打开 AdventureWorks.csdl 文件并找到 SalesOrderHeader 实体的定义。

  2. 查找子 Status 元素,然后添加以下属性:

    ConcurrencyMode="fixed"
    
  3. 保存对 AdventureWorks.csdl 的更改。

  4. 在以下示例代码中,在 foreach 循环(在 Visual Basic 中为 For Each)后设置断点,并在调试模式下运行应用程序。

  5. 当执行断开后,使用 SQL Server Management Studio 以针对 AdventureWorks 数据库执行以下 Transact-SQL 命令:

    UPDATE Sales.SalesOrderHeader SET Status = 1 WHERE CreditCardApprovalCode IS NULL.
    
  6. 重新启动程序执行。

示例

在本示例中,当执行上述过程后,对 SalesOrderHeader 对象的 Status 属性所做的更改将导致出现 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());
    }
}

另请参见

概念

使用对象(实体框架)