Cómo administrar la simultaneidad de datos en un contexto del objeto (Entity Framework)

En este tema se proporciona un ejemplo de cómo administrar la simultaneidad en un contexto del objeto. En este tema, generará y administrará una OptimisticConcurrencyException al actualizar la propiedad Status del objeto SalesOrderHeader. Para obtener más información, vea Guardar los cambios y administrar la simultaneidad (Entity Framework).

El ejemplo de este tema se basa en el modelo Adventure Works Sales. Para ejecutar el código de este ejemplo, debe haber agregado ya el modelo AdventureWorks Sales al proyecto y haber configurado el proyecto para usar Entity Framework. Para ello, complete los procedimientos de Cómo configurar manualmente un proyecto de Entity Framework y Cómo: Definir manualmente los archivos de asignación y modelo (Entity Framework).

Para generar correctamente una OptimisticConcurrencyException, debe modificar la propiedad Status en el archivo de asignación conceptual.

Para habilitar la comprobación de simultaneidad en la propiedad Status

  1. Abra el archivo AdventureWorks.csdl y busque la definición de la entidad SalesOrderHeader.

  2. Busque el elemento Status secundario y agregue el atributo siguiente:

    ConcurrencyMode="fixed"
    
  3. Guarde los cambios realizados en AdventureWorks.csdl.

  4. En el código de ejemplo siguiente, establezca un punto de interrupción después del bucle foreach (For Each en Visual Basic) y ejecute la aplicación en el modo de depuración.

  5. Cuando la ejecución se interrumpa, use SQL Server Management Studio para ejecutar el siguiente comando de Transact-SQL con la base de datos AdventureWorks:

    UPDATE Sales.SalesOrderHeader SET Status = 1 WHERE CreditCardApprovalCode IS NULL.
    
  6. Reinicie la ejecución del programa.

Ejemplo

En este ejemplo, los cambios en la propiedad Status del objeto SalesOrderHeader ocasionan una OptimisticConcurrencyException cuando se sigue el procedimiento anterior.

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

Vea también

Conceptos

Trabajar con objetos (Entity Framework)