How to Apply Changes Made to a Detached Object without passing it or retrieving it in .NET Framework 3.5 ADO.NET Entity Framework

If you are using .NET Framework 3.5 ADO.NET Entity Framework inside a Web Service the solution proposed at MSDN in How to Apply changes to a Detached object may not be the best solution.

How to: Apply Changes Made to a Detached Object (Entity Framework)

Both approaches has the following disadvantages:

  • Pass original and updated item to apply changes (Traffic duplication)

  • Pass updated item and query for original item to apply changes (Extra access to BD to retrieve item)

What we want is to be able to update the item, using the values passed by the Web Service, without having the original item or querying the database for it.

This can happen in the following scenarios:

  • Internal entity model can be different from data contract types

  • Applications consuming service don't want to use Message Exchange Pattern

  • Don't retrieve item if it's a full update, only retrieve in partial update.


ADO.NET Entity Framework allows us to update an item if you have an EntityKey for the item, using generics we can encapsulate the key creation in the following function.

   1:          #region CreateEntityKey
   3:          /// <summary>
   4:          /// Create Entity Key
   5:          /// </summary>
   6:          public static EntityKey CreateEntityKey<TDomainObjectContextKey, TDomainObjectKey>()
   7:          {
   8:              // Parent Keys
   9:              EntityKey _entityKey = new EntityKey();
  11:              _entityKey.EntityContainerName = typeof( TDomainObjectContextKey ).Name;
  12:              _entityKey.EntitySetName = typeof( TDomainObjectKey ).Name;
  14:              return _entityKey;
  15:          }
  17:          #endregion

Since the object already exists in the Database what we need is to create a Relationship Key and add it to our item.

The following examples shows this method applied to a context ( LookupEntities ) that has two entities( LookupType, LookupValue), where a LookupType has many LookupValues.

We want to add a LookupValue to an existing LookupType. So create the EntityKey for the item and populate it with the parent item ID (foreign key) that is one of the fields of the entity.

Now that we have our EntityKey created we add it to the item, attach the item to the context and save the changes.

   1:          #region Update
   3:          /// <summary>
   4:          /// Update a LookupValue
   5:          /// </summary>
   6:          /// <param name="context"></param>
   7:          /// <param name="item"></param>
   8:          /// <returns></returns>
   9:          public Int32 Update(
  10:              LookupEntities context,
  11:              LookupValue item )
  12:          {
  13:              #region Create Relationship Key
  15:              // Create Relationship Key
  16:              EntityKey _relationshipKey = CreateEntityKey<LookupEntities, LookupType>();
  18:              _relationshipKey.EntityKeyValues = new EntityKeyMember[2]{
  19:                  new EntityKeyMember("LookupTypeID",item.LookupTypeID),
  20:                  new EntityKeyMember("Culture",item.Culture)};
  22:              // Create LookupType Reference
  23:              item.LookupTypeReference = new EntityReference<LookupType>();
  24:              item.LookupTypeReference.EntityKey = _relationshipKey;
  26:              #endregion
  28:              #region Attach Item
  30:              // Attach Item
  31:              context.AttachTo(typeof(LookupValue).Name, item); 
  33:              #endregion
  36:              #region Save changes
  38:              // Save changes pessimistically. This means that changes 
  39:              // must be accepted manually once the transaction succeeds.
  40:              context.SaveChanges();
  42:              #endregion
  44:              return item.LookupValueID;
  45:          }
  47:          #endregion

With this method we improve performance in applying changes to detached objects, avoiding traffic duplication and extra access to the database to maintain the context updated.

Pedro M. Pinheiro

Comments (2)
  1. shake says:

    I tried ur method and it is not working for me. No changes to the object are saved (using the NorthwindEF database):

    Product product = GetDetachedProductById(92);

    product.ProductName = "asdf";



    void UpdateDetachedProductById(Products product)


               using (NorthwindEFEntities entities = new NorthwindEFEntities())


                   EntityKey _categoryRelationshipKey = CreateEntityKey<NorthwindEFEntities, Categories>();

                   _categoryRelationshipKey.EntityKeyValues = new EntityKeyMember[1]{

                       new EntityKeyMember("CategoryID",1)};

                   EntityKey _supplierRelationshipKey = CreateEntityKey<NorthwindEFEntities, Suppliers>();

                   _supplierRelationshipKey.EntityKeyValues = new EntityKeyMember[1]{

                       new EntityKeyMember("SupplierID",1)};

                   product.CategoriesReference.EntityKey = _categoryRelationshipKey;

                   product.SuppliersReference.EntityKey = _supplierRelationshipKey;





  2. Tom says:

    This code does not work as stated.

Comments are closed.

Skip to main content