How to: Change Relationships Between POCO Entities

When the creation of proxy objects is disabled or when a POCO entity is created without its proxy object, you must call the DetectChanges method on the ObjectContext to synchronize the changes with the ObjectStateManager. In addition to detecting changes in scalar properties, this method detects changes in relationships, including adding, deleting, or changing a related object. For more information, see Tracking Changes in POCO Entities. The SaveChanges method calls DetectChanges, so you do not have to call DetectChanges explicitly if you do not need immediate synchronization of the relationships.

The example in this topic uses the POCO custom data 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 changes the current contact for an order to a different contact. The DetectChanges method is called by the SaveChanges method before changes are saved to the data source.

Using context As New POCOAdventureWorksEntities()
    ' Disable proxy object creation. 
    context.ContextOptions.ProxyCreationEnabled = False
    Try
        ' Define the order and new address IDs. 
        Dim orderId As Integer = 43659
        Dim differentContactID As Integer = 5

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

        ' Get contact to change to. 
        Dim differentContact As Contact = context.Contacts.First(Function(c) c.ContactID = differentContactID)

        ' The current contact. 
        Console.WriteLine("Original Contact Name: {0}", order.Contact.FirstName)

        ' The Entity Framework takes care of setting the other end of the relationship 
        ' when you call DetectChanges or SaveChanges (which calls DetectChanges). 
        ' However, there are scenarios when you are not working with ObjectContext 
        ' and will want to fix both ends of the relationship yourself 
        ' (for example, when working with disconnected objects). 

        ' Change the current ContactID to the new ContactID. 
        order.ContactID = differentContact.ContactID

        ' Because the change tracking is not enabled 
        ' The state manager will not be updated untill DetectChanges is called. 
        ' If context.ContextOptions.ProxyCreationEnabled was set to true (which is the default) 
        ' The changes would be synchronized righ away. 
        Console.WriteLine("The contact was updated, but DetectChanges was not yet called. ")
        Console.WriteLine("Contact Name: {0}", order.Contact.FirstName)
        context.DetectChanges()
        Console.WriteLine("After DetectChanges was called. Contact Name: {0}", order.Contact.FirstName)

        ' Call save the changes, which calls DetectChanges. 
        context.SaveChanges()
    Catch ex As UpdateException
        Console.WriteLine(ex.ToString())
    Catch ex As InvalidOperationException
        Console.WriteLine(ex.ToString())
    End Try
End Using
using (POCOAdventureWorksEntities context =
        new POCOAdventureWorksEntities())
{
    // Disable proxy object creation.
    context.ContextOptions.ProxyCreationEnabled = false;
    try
    {
        // Define the order and new address IDs.
        int orderId = 43659;
        int differentContactID = 5;

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

        // Get contact to change to.
        Contact differentContact = context.Contacts.
            First(c => c.ContactID == differentContactID);
        
        // The current contact.
        Console.WriteLine("Original Contact Name: {0}", order.Contact.FirstName);

        // The Entity Framework takes care of setting the other end of the relationship
        // when you call DetectChanges or SaveChanges (which calls DetectChanges).
        // However, there are scenarios when you are not working with ObjectContext
        // and will want to fix both ends of the relationship yourself
        // (for example, when working with disconnected objects). 

        // Change the current ContactID to the new ContactID.
        order.ContactID = differentContact.ContactID;

        // Because the change tracking is not enabled
        // The state manager will not be updated untill DetectChanges is called.
        // If context.ContextOptions.ProxyCreationEnabled was set to true (which is the default)
        // The changes would be synchronized righ away. 
        Console.WriteLine("The contact was updated, but DetectChanges was not yet called. ");
        Console.WriteLine("Contact Name: {0}", order.Contact.FirstName);
        context.DetectChanges();
        Console.WriteLine("After DetectChanges was called. Contact Name: {0}",
            order.Contact.FirstName);

        // Call save the changes, which calls DetectChanges.
        context.SaveChanges();
    }
    catch (UpdateException ex)
    {
        Console.WriteLine(ex.ToString());
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

See Also

Concepts

Working with POCO Entities