How to: Attach Related Objects (Entity Framework)

This topic provides examples of how to attach related objects to an object context. For more information, see Attaching Objects (Entity Framework). This procedure is used when reconstructing a graph of objects that was serialized using XML serialization.

The example in this topic is based on the Adventure Works Sales Model. To run the code in this example, you must have already added the AdventureWorks Sales Model to your project and configured your project to use the Entity Framework. To do this, complete the procedures in How to: Manually Configure an Entity Framework Project and How to: Manually Define an Entity Data Model (Entity Framework).

Example

This example attaches a collection of detached SalesOrderDetail objects and a detached SalesOrderHeader object to an object context and then defines the relationships between the SalesOrderHeader object and each SalesOrderDetail object.

Private Shared Sub AttachRelatedObjects( _
ByVal currentContext As ObjectContext, _
ByVal detachedOrder As SalesOrderHeader, _
ByVal detachedItems As List(Of SalesOrderDetail))
    Try
        ' Attach the root detachedOrder object to the supplied context.
        currentContext.Attach(detachedOrder)

        ' Attach each detachedItem to the context, and define each relationship
        ' by attaching the attached SalesOrderDetail object to the EntityCollection on 
        ' the SalesOrderDetail navigation property of the now attached detachedOrder.
        For Each item As SalesOrderDetail In detachedItems
            currentContext.Attach(item)
            detachedOrder.SalesOrderDetail.Attach(item)
        Next

    Catch ex As InvalidOperationException
        Console.WriteLine(ex.ToString())
    End Try
End Sub
private static void AttachRelatedObjects(
    ObjectContext currentContext,
    SalesOrderHeader detachedOrder,
    List<SalesOrderDetail> detachedItems)
{
    try
    {
        // Attach the root detachedOrder object to the supplied context.
        currentContext.Attach(detachedOrder);

        // Attach each detachedItem to the context, and define each relationship
        // by attaching the attached SalesOrderDetail object to the EntityCollection on 
        // the SalesOrderDetail navigation property of the now attached detachedOrder.
        foreach (SalesOrderDetail item in detachedItems)
        {
            currentContext.Attach(item);
            detachedOrder.SalesOrderDetail.Attach(item);
        }
    }
    catch (InvalidOperationException ex)
    {
        Console.WriteLine(ex.GetType().ToString() + ": " + ex.ToString());
    }
}

This example adds a collection of detached SalesOrderDetail objects to a detached SalesOrderHeader object and then attaches this object graph to the object context.

Private Shared Sub AttachObjectGraph( _
ByVal currentContext As ObjectContext, _
ByVal detachedOrder As SalesOrderHeader, _
ByVal detachedItems As List(Of SalesOrderDetail))
    Try
        ' Define the relationships by adding each SalesOrderDetail 
        ' object in the detachedItems List<SalesOrderDetail> collection to the 
        ' EntityCollection on the SalesOrderDetail navigation property of detachedOrder.
        For Each item As SalesOrderDetail In detachedItems
            detachedOrder.SalesOrderDetail.Add(item)
        Next

        ' Attach the object graph to the supplied context.
        currentContext.Attach(detachedOrder)

    Catch ex As InvalidOperationException
        Console.WriteLine(ex.ToString())
    End Try
End Sub
private static void AttachObjectGraph(
    ObjectContext currentContext,
    SalesOrderHeader detachedOrder, 
    List<SalesOrderDetail> detachedItems)
{
        try
        {
            // Define the relationships by adding each SalesOrderDetail 
            // object in the detachedItems List<SalesOrderDetail> collection to the 
            // EntityCollection on the SalesOrderDetail navigation property of detachedOrder.
            foreach (SalesOrderDetail item in detachedItems)
            {
                detachedOrder.SalesOrderDetail.Add(item);
            }

            // Attach the object graph to the supplied context.
            currentContext.Attach(detachedOrder);
        }
        catch (InvalidOperationException ex)
        {
            Console.WriteLine(ex.GetType().ToString() + ": " + ex.ToString());
        }
}

This example creates an instance of EntityKey by using a specified key name, key value, and the qualified entity set name. This key is then used to attach an object and define a relationship without explicitly loading the parent object.

' Specify the order to which to add the item.
Dim orderId = 43680

' Create the key that represents the order.
Dim orderKey As EntityKey = _
    New EntityKey("AdventureWorksEntities.SalesOrderHeader", _
        "SalesOrderID", orderId)

' Create an order that we can attach.
Dim order As New SalesOrderHeader()
order.EntityKey = orderKey

' Ensure that the ID property matches the key.
order.SalesOrderID = CType(orderKey.EntityKeyValues(0).Value, Integer)

Using context As AdventureWorksEntities = _
    New AdventureWorksEntities()
    Try
        ' Attach the newly created object.
        context.Attach(order)

        ' Create a new item using the static Create method 
        ' and add it to the attached order.
        order.SalesOrderDetail.Add( _
            SalesOrderDetail.CreateSalesOrderDetail(0, _
            0, 2, 750, 1, Convert.ToDecimal(2171.2942), 0, 0, _
            Guid.NewGuid(), DateTime.Today))

        context.SaveChanges()
    Catch ex As InvalidOperationException
        Console.WriteLine(String.Format("Ensure that the key value '{0}' " _
            & "matches the value of the '{1}' property.", _
            order.EntityKey.EntityKeyValues(0).Value, _
            order.EntityKey.EntityKeyValues(0).Key))
    Catch ex As UpdateException
        Console.WriteLine(String.Format("An error has occured. Ensure that " _
        & "an object with an value of '{0}' for key property '{1}' exists.", _
        order.EntityKey.EntityKeyValues(0).Value, _
        order.EntityKey.EntityKeyValues(0).Key))
    End Try
End Using
// Specify the order to which to add the item.
int orderId = 43680;

// Create the key that represents the order.
EntityKey orderKey =
    new EntityKey("AdventureWorksEntities.SalesOrderHeader",
        "SalesOrderID", orderId);

// Create an order that we can attach.
SalesOrderHeader order = new SalesOrderHeader();
order.EntityKey = orderKey;

// Ensure that the ID property matches the key.
order.SalesOrderID = (int)orderKey.EntityKeyValues[0].Value;

using (AdventureWorksEntities context =
    new AdventureWorksEntities())
{
    try
    {
        // Attach the newly created object.
        context.Attach(order);

        // Create a new item using the static Create method 
        // and add it to the attached order.
        order.SalesOrderDetail.Add(
            SalesOrderDetail.CreateSalesOrderDetail(0,
            0, 2, 750, 1, (decimal)2171.2942, 0, 0,
            Guid.NewGuid(), DateTime.Today));

        context.SaveChanges();
    }
    catch (InvalidOperationException)
    {
        Console.WriteLine(String.Format("Ensure that the key value '{0}' "
            + "matches the value of the '{1}' property.",
            order.EntityKey.EntityKeyValues[0].Value,
            order.EntityKey.EntityKeyValues[0].Key));
    }
    catch (UpdateException)
    {
        Console.WriteLine(String.Format("An error has occured. Ensure that "
        + "an object with an value of '{0}' for key property '{1}' exists.",
        order.EntityKey.EntityKeyValues[0].Value,
        order.EntityKey.EntityKeyValues[0].Key));
    }
}

See Also

Concepts

Serializing Objects (Entity Framework)
Web Services and the Entity Data Model (Application Scenarios)

Other Resources

Managing the Object Context (Entity Framework)
Working with Objects (Entity Framework Tasks)