This documentation is archived and is not being maintained.

How to: Manage Data Concurrency in the Object Context

This topic provides an example of how to manage concurrency in an object context. The example in this topic demonstrates a scenario in which you want to make sure that saving changes made to your object on the client succeed whether or not any intermediate changes were made to the database. You will generate and handle an OptimisticConcurrencyException when updating the Status property of SalesOrderHeader object.

Bb399228.note(en-us,VS.100).gifNote:
The way you handle concurrency exceptions depends on the business rules required by your application. Mike Taulty discusses some considerations and possible ways to handle concurrency conflicts in the following blog: On Entity Framework, Concurrency.

The example in this topic is based on the Adventure Works Sales Model. To run the code in this example, you must have already added the AdventureWorks Sales Model to your project and configured your project to use the Entity Framework. To do this, complete the procedures in How to: Manually Configure an Entity Framework Project and How to: Manually Define the Model and Mapping Files.

To successfully generate an OptimisticConcurrencyException, you must modify the Status property in the conceptual mapping file.

To enable concurrency checking on the Status property

  1. Open the AdventureWorks.csdl file and locate the definition for the SalesOrderHeader entity.

  2. Find the child Status element, and add the following attribute:

    ConcurrencyMode="fixed"
    
  3. Save changes to AdventureWorks.csdl.

  4. In the following example code, set a breakpoint after the foreach loop (For Each in Visual Basic) and run the application in debug mode.

  5. When the execution breaks, use SQL Server Management Studio to execute the following Transact-SQL command against the AdventureWorks database:

    UPDATE Sales.SalesOrderHeader SET Status = 1 WHERE CreditCardApprovalCode IS NULL.
    
  6. Restart program execution.

Example

In this example, changes to the Status property of the SalesOrderHeader object cause an OptimisticConcurrencyException when the procedure above is followed.

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());
    }
}

See Also

Show: