Compartir a través de


Guardar los cambios y administrar la simultaneidad (Entity Framework)

Entity Framework implementa un modelo de simultaneidad optimista. Esto significa que los bloqueos no se mantienen en los datos en el origen de datos. Sin embargo, Servicios de objeto guarda los cambios en la base de datos sin comprobar la simultaneidad de forma predeterminada. Para las propiedades que podrían experimentar un alto grado de simultaneidad, recomendamos que la propiedad de entidad se defina en el nivel conceptual con un atributo ConcurrencyMode="fixed", como se muestra en el ejemplo siguiente:

<Property Name="Status" Type="Byte" Nullable="false" ConcurrencyMode="Fixed" />

Cuando se utiliza este atributo, Servicios de objeto comprueba si hay cambios en la base de datos antes de guardarlos en ella. Cualquier cambio en conflicto ocasionará una OptimisticConcurrencyException. Para obtener más información, vea Cómo administrar la simultaneidad de datos en un contexto del objeto (Entity Framework). También puede producirse una excepción OptimisticConcurrencyException cuando se define un modelo Entity Data Model que utiliza procedimientos almacenados para realizar actualizaciones en el origen de datos. En este caso, la excepción se produce cuando el procedimiento almacenado que se utiliza para realizar actualizaciones notifica que se actualizaron cero filas. Para obtener más información, vea Compatibilidad con los procedimientos almacenados (Entity Framework).

Cuando se realizan actualizaciones en escenarios de este tipo con una gran simultaneidad, ser recomienda llamar a Refresh con frecuencia. Al llamar a Refresh, el RefreshMode controla cómo se propagan los cambios. La opción StoreWins hará que Servicios de objeto sobrescriba todos los datos en la memoria caché de objetos con los valores correspondientes de la base de datos. A la inversa, la opción ClientWins reemplaza los valores originales en la memoria caché por los valores más recientes del origen de datos. De este modo se garantiza que todos datos modificados en la memoria caché de objetos pueden volverse a guardar correctamente en el origen de datos, eliminando los conflictos entre los cambios que se realizaron en los datos en la memoria caché y los cambios que se efectuaron en los mismos datos en el origen de datos.

Llame al método Refresh después de llamar al método SaveChanges si las actualizaciones en el origen de datos pueden modificar los datos que pertenecen a otros objetos en el contexto del objeto. Por ejemplo, en el modelo AdventureWorks Sales, cuando se agrega un nuevo SalesOrderDetail, se desencadena la actualización de la columna SubTotal para reflejar el subtotal con el nuevo elemento. En este caso, llame al método Refresh y pase el objeto SalesOrderHeader para el pedido. De este modo se garantiza que los valores generados por el desencadenador se devuelven al objeto SalesOrderHeader en el contexto del objeto.

Servicios de objeto realiza el seguimiento de los cambios que se han efectuado en los objetos de la memoria caché. Cuando se llama al método SaveChanges, Servicios de objeto intenta combinar de nuevo los cambios en el origen de datos. Se puede generar un error en SaveChanges y producirse una excepción OptimisticConcurrencyException cuando los cambios en los datos de la memoria caché de objetos entran en conflicto con los cambios que se realizaron en el origen de datos después de agregarse objetos a la memoria caché o actualizarse en ella. Esto hace que toda la transacción se revierta. Cuando se produce una excepción OptimisticConcurrencyException, se debe controlar llamando a Refresh y especificando si el conflicto se debe resolver conservando los datos en los datos de objeto (StoreWins) o actualizando la memoria caché de objetos con los datos del origen de datos (ClientWins), como en el ejemplo siguiente:

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

SaveChanges puede generar una excepción UpdateException cuando un objeto agregado a ObjectContext no se puede crear correctamente en el origen de datos. Esto puede suceder si ya existe una fila con la clave externa especificada por la relación. Cuando esto sucede, no se puede utilizar Refresh para actualizar el objeto agregado en el contexto del objeto. En su lugar, hay que volver a cargar el objeto con un valor de OverwriteChanges para MergeOption.

Para obtener más información acerca de cómo administrar el contexto del objeto, vea Cómo administrar la simultaneidad de datos en un contexto del objeto (Entity Framework).

Servicios de objeto también observa las transacciones que se definen utilizando el espacio de nombres System.Transactions. Para obtener más información, vea Administrar transacciones en Servicios de objeto (Entity Framework).

Vea también

Conceptos

Agregar, modificar y eliminar objetos (Entity Framework)

Otros recursos

Trabajar con objetos (Entity Framework)