Saturday, August 06, 2011

AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.

AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges.

I got this error while working with WCF, Entity Framework 4.0 and C#.Net 2010, I had one object bind with parent child relationship and when I tried to delete record from child object first and then from parent object, that time I got this error. 
Basically when you have relational entity object and want to execute all delete operation in single transaction, then you have to attach the object into the context and then remove it, instead of doing ApplyChanges(), this method will maintain the object key’s into ObjectStateManager and when you try to remove data from parent object then It will throw this error. I spend enough time to find the solution of this error.

Let’s say you have object structure like below

public class Country
{
   //Default Constructor
   public Country() { CountryState = new List<States>(); }
   public string Name { get; set; }
   public int Id { get; set; }
   public List<States> CountryState { get; set; }
} 
public class States
{
   public string Name { get; set; }
   public int Id { get; set; }       
}

All data I have in “countryObject”

//Load this object with actual data
List<Country> countryObject = new List<Country>();

Now the code I got this error is below

using (var ctx = DataBaseContext)
{
   using (var tc = new TransactionScope())
   {
      foreach (Country con in countryObject)
       {
         foreach (States sat in con.CountryState)
         {
            //Delete Data from CHIILD Table/Object
            sat.MarkAsDeleted();
            ctx.States.ApplyChanges(sat);
         } 

         //Delete Data from PARENT Table/Object
         con.MarkAsDeleted();
         ctx.Country.ApplyChanges(con); //ERROR                    
        } 
        //Save the Changes
        ctx.SaveChanges(); 
        //Commit the transaction
        tc.Complete();
      }
 }

The code I resolved this error

using (var ctx = ServiceUtility.Context)
{
   using (var tc = new TransactionScope())
   {
       foreach (Country con in countryObject)
       {
         foreach (States sat in con.CountryState)
         {
           //Delete Data from CHIILD Table/Object
           sat.MarkAsDeleted();
           ctx.States.Attach(sat);
           ctx.States.DeleteObject(sat);
         } 
         
//Delete Data from PARENT Table/Object
       con.MarkAsDeleted();
       ctx.Country.Attach(con);
       ctx.Country.DeleteObject(con);
      } 
    //Save the Changes
    ctx.SaveChanges();
    //Commit the transaction
    tc.Complete();
  }
}


Note: if you use ctx.SaveChanges(); in a loop or after every Deleteobject() method then you might get following error
"Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries." 

1 comment:

Ghennady said...

class Program
{
static void Main( string[] args )
{
using( var service = new SaleClient() )
{
Customer customer = service.GetCustomer();

Order order = new Order() { Name = "Order1" };

customer.Orders.Add( order );

service.Save( customer );

order .AcceptChanges();
customer.AcceptChanges();

order.Name += "1";

service.Save( customer );
}
}
}

I have the same error in last save
could you help?