Cómo: Detectar cambios en entidades POCO

Este tema muestra cómo realizar el seguimiento de cambios en entidades POCO mediante objetos proxy de seguimiento de cambios. También muestra cómo detectar los cambios sin objetos proxy, mediante una llamada al método DetectChanges. Tenga en cuenta que, de forma predeterminada, el método SaveChanges llamará primero al método DetectChanges. Para obtener más información, vea Realizar el seguimiento de los cambios en entidades POCO (Entity Framework).

Los ejemplos de este tema utilizan las clases POCO que se definen en Cómo: Definir entidades POCO (Entity Framework) y un modelo de datos basado en AdventureWorks que se define en Cómo: Personalizar archivos de asignación y modelado para trabajar con objetos personalizados (Entity Framework).

Ejemplo

En este ejemplo se agrega un proxy de seguimiento propio de POCO, el cual permite a Entity Framework realizar el seguimiento de cambios en la entidad POCO.

' Specify the order to update. 
Dim orderId As Integer = 43680

Using context As New POCOAdventureWorksEntities()
    Try
        ' Enable lazy loading. 
        context.ContextOptions.LazyLoadingEnabled = True

        Dim order As Order = context.Orders.Where(Function(o) o.SalesOrderID = orderId).First()
        ' Create a new item and add it to the order. 
        ' The Entity Framework is going to generate 
        ' proxy object for the newItem object. 
        Dim newItem As LineItem = context.CreateObject(Of LineItem)()
        newItem.SalesOrderDetailID = 0
        ' Assign the order to the new LineItem. 
        newItem.SalesOrderID = orderId
        newItem.OrderQty = 1
        newItem.ProductID = 750
        newItem.UnitPriceDiscount = 0
        newItem.UnitPrice = 2171.2942D
        newItem.ModifiedDate = DateTime.Today
        newItem.rowguid = Guid.NewGuid()
        newItem.SpecialOfferID = 1


        ' Add the new item to the order. 
        ' The order will be added to the context because 
        ' we are working with POCO proxies. 
        order.LineItems.Add(newItem)

        ' The state of the newItem is Added. 
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State.ToString())

        ' Change the status and ship date of an existing order. 
        order.ShipDate = DateTime.Today

        ' The sate of the order item is Modified. 
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(order).State.ToString())

        ' The newItem is set to Unchanged.
        context.SaveChanges()

        ' Change the newly added item. 
        newItem.OrderQty = 2

        ' The changes are tracked as they occur and the state of the object is Modified. 
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State.ToString())

        ' Delete the newly created object. 
        context.DeleteObject(newItem)

        ' Save changes in the object context to the database 
        ' after first detecting changes again. 
        context.SaveChanges()
    Catch ex As UpdateException
        Console.WriteLine(ex.ToString())
    Catch ex As InvalidOperationException
        Console.WriteLine(ex.ToString())
    End Try
End Using
// Specify the order to update.
int orderId = 43680;

using (POCOAdventureWorksEntities context =
        new POCOAdventureWorksEntities())
{
    try
    {
        // Enable lazy loading.
        context.ContextOptions.LazyLoadingEnabled = true;

        Order order = context.Orders.
                          Where(o => o.SalesOrderID == orderId).First();
        // Create a new item and add it to the order.
        // The Entity Framework is going to generate 
        // proxy object for the newItem object. 
        LineItem newItem = context.CreateObject<LineItem>();
        newItem.SalesOrderDetailID = 0;
        // Assign the order to the new LineItem. 
        newItem.SalesOrderID = orderId;
        newItem.OrderQty = 1;
        newItem.ProductID = 750;
        newItem.UnitPriceDiscount = 0;
        newItem.UnitPrice = 2171.2942M;
        newItem.ModifiedDate = DateTime.Today;
        newItem.rowguid = Guid.NewGuid();
        newItem.SpecialOfferID = 1;

        // Add the new item to the order.
        // The order will be added to the context because 
        // we are working with POCO proxies.
        order.LineItems.Add(newItem);

        // The state of the newItem is Added.
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State);

        // Change the status and ship date of an existing order.
        order.ShipDate = DateTime.Today;

        // The sate of the order item is Modified.
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(order).State);

        // The newItem is set to Unchanged.
        context.SaveChanges();

        // Change the newly added item.
        newItem.OrderQty = 2;

        // The changes are tracked as they occur and the state of the object is Modified.
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State);

        // Delete the newly created object.
        context.DeleteObject(newItem);

        // Save changes in the object context to the database 
        // after first detecting changes again.
        context.SaveChanges();
    }
    catch (UpdateException ex)
    {
        Console.WriteLine(ex.ToString());
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

En este ejemplo se agrega una entidad POCO que no recibe un seguimiento de ObjectContext. Se llama al método DetectChanges para sincronizar el ObjectStateManager con el estado actual de los objetos.

' Specify the order to update. 
Dim orderId As Integer = 43680
Using context As New POCOAdventureWorksEntities()
    Try
        ' Disable proxy object creation. 
        context.ContextOptions.ProxyCreationEnabled = False

        Dim order As Order = context.Orders.Include("LineItems").Where(Function(o) o.SalesOrderID = orderId).First()


        ' Create a new item and add it to the order. 
        ' The Entity Framework is not going to generate 
        ' a proxy object for the newItem object. 
        Dim newItem As New LineItem()
        newItem.SalesOrderDetailID = 0
        ' Assign the order to the new LineItem. 
        newItem.SalesOrderID = orderId
        newItem.OrderQty = 1
        newItem.ProductID = 750
        newItem.UnitPriceDiscount = 0
        newItem.UnitPrice = 2171.2942D
        newItem.ModifiedDate = DateTime.Today
        newItem.rowguid = Guid.NewGuid()
        newItem.SpecialOfferID = 1

        ' Add the new item to the order. 
        ' The order will not be added to the context because 
        ' we are working with pure POCO objects. 
        order.LineItems.Add(newItem)

        Dim entry As ObjectStateEntry = Nothing
        ' There is no entry for the object because it is not in the context. 
        context.ObjectStateManager.TryGetObjectStateEntry(newItem, entry)
        Console.WriteLine("{0}", If(entry IsNot Nothing, entry.State.ToString(),
                                    "There is no entry for this object"))

        ' Call DetectChanges to synchronize the objects with the state manager. 
        context.DetectChanges()

        ' Try getting the entry after Detectchagnes was called. 
        context.ObjectStateManager.TryGetObjectStateEntry(newItem, entry)
        Console.WriteLine("{0}", If(entry IsNot Nothing, entry.State.ToString(),
                                    "There is no entry for this object"))

        ' Change the status and ship date of an existing order. 
        order.ShipDate = DateTime.Today

        ' Even though we changed the ShipDate of the item in the context 
        ' the status of the order is still Unchanged. 
        ' The changes to the POCO entity without the chane tracking proxy 
        ' are not tracked as they occur. 
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(order).State.ToString())

        ' Calls DetectChanges(). The newItem is set to Unchanged.
        context.SaveChanges()

        ' Change the newly added item. 
        newItem.OrderQty = 2

        ' The state of the newItem is Unchanged. 
        ' If the newItem was a POCO proxy entity the changes would be tracked as they occur 
        ' and the state would be Modified. 
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State.ToString())

        ' Call DetectChanges to synchronize the objects with the state manager. 
        context.DetectChanges()

        ' The state of the newItem is now Modified. 
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State.ToString())

        ' Delete the newly created object. 
        context.DeleteObject(newItem)

        ' Save changes in the object context to the database 
        ' after first detecting changes again. 
        context.SaveChanges()
    Catch ex As UpdateException
        Console.WriteLine(ex.ToString())
    Catch ex As InvalidOperationException
        Console.WriteLine(ex.ToString())
    End Try
End Using
// Specify the order to update.
int orderId = 43680;
using (POCOAdventureWorksEntities context =
        new POCOAdventureWorksEntities())
{
    try
    {
        // Disable proxy object creation. 
        context.ContextOptions.ProxyCreationEnabled = false;

        Order order = context.Orders.Include("LineItems").
                          Where(o => o.SalesOrderID == orderId).First();


        // Create a new item and add it to the order.
        // The Entity Framework is not going to generate 
        // a proxy object for the newItem object. 
        LineItem newItem = new LineItem();
        newItem.SalesOrderDetailID = 0;
        // Assign the order to the new LineItem. 
        newItem.SalesOrderID = orderId;
        newItem.OrderQty = 1;
        newItem.ProductID = 750;
        newItem.UnitPriceDiscount = 0;
        newItem.UnitPrice = 2171.2942M;
        newItem.ModifiedDate = DateTime.Today;
        newItem.rowguid = Guid.NewGuid();
        newItem.SpecialOfferID = 1;

        // Add the new item to the order.
        // The order will not be added to the context because
        // we are working with pure POCO objects.
        order.LineItems.Add(newItem);

        ObjectStateEntry entry = null;
        // There is no entry for the object because it is not in the context.
        context.ObjectStateManager.TryGetObjectStateEntry(newItem, out entry);
        Console.WriteLine("{0}", entry!=null ? entry.State.ToString() : "There is no entry for this object");

        // Call DetectChanges to synchronize the objects with the state manager.
        context.DetectChanges();

        // Try getting the entry after Detectchagnes was called.
        context.ObjectStateManager.TryGetObjectStateEntry(newItem, out entry);
        Console.WriteLine("{0}", entry != null ? entry.State.ToString() : "There is no entry for this object");

        // Change the status and ship date of an existing order.
        order.ShipDate = DateTime.Today;

        // Even though we changed the ShipDate of the item in the context 
        // the status of the order is still Unchanged. 
        // The changes to the POCO entity without the chane tracking proxy
        // are not tracked as they occur.
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(order).State);

        // Calls DetectChanges(). The newItem is set to Unchanged.
        context.SaveChanges();

        // Change the newly added item.
        newItem.OrderQty = 2;

        // The state of the newItem is Unchanged.
        // If the newItem was a POCO proxy entity the changes would be tracked as they occur
        // and the state would be Modified.
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State);

        // Call DetectChanges to synchronize the objects with the state manager.
        context.DetectChanges();

        // The state of the newItem is now Modified.
        Console.WriteLine(context.ObjectStateManager.GetObjectStateEntry(newItem).State);

        // Delete the newly created object.
        context.DeleteObject(newItem);

        // Save changes in the object context to the database 
        // after first detecting changes again.
        context.SaveChanges();
    }
    catch (UpdateException ex)
    {
        Console.WriteLine(ex.ToString());
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

Vea también

Tareas

Cómo: Cambiar las relaciones entre entidades POCO (Entity Framework)

Conceptos

Personalizar objetos (Entity Framework)
Trabajar con entidades POCO (Entity Framework)