How to: Detect Changes in POCO Entities

This topic shows how to track changes in POCO entities by using a change-tracking proxies. It also shows how to detect changes without proxies, by calling the DetectChanges method. Note, that by default the SaveChanges method will first call the DetectChanges method. For more information, see Tracking Changes in POCO Entities.

The examples in this topic use the POCO classes that are defined in How to: Define POCO Entities and an AdventureWorks-based data model that is defined in How to: Customize Modeling and Mapping Files to Work with Custom Objects.

Example

This example adds a POCO self-tracking proxy, which allows the Entity Framework to track changes in the POCO entity.

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

This example adds a POCO entity that is not tracked by the ObjectContext. The DetectChanges method is called to synchronize the ObjectStateManager with the current state of the objects.

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

See Also

Tasks

How to: Change Relationships Between POCO Entities

Concepts

Customizing Objects
Working with POCO Entities