none
Cloning And Saving Entity Object with Child Objects RRS feed

  • Question

  • Good Morning,

    I'm trying clone an entity object and save it as a different object.  The entity object I am trying to clone is called a TemperatureControllerConfigurationGroup.  A TemperatureControllerConfigurationGroup contains one or more TemperatureControllerConfigurations which, in turn, contains one or more TemperatureControllerChannelConfigurations.  So, we end up with something like this:

    TemperatureControllerConfigurationGroup 1 ---- * TemperatureControllerConfiguration 1 ---- * TemperatureControllerChannelConfiguration

    The code to accomplish this task is as follows:

          . . .
    	  var clonedTemperatureControllerConfigurationGroup = this.Clone(temperatureControllerConfigurationGroup);
                this.DetachTemperatureControllerConfigurationGroupObjects(temperatureControllerConfigurationGroup);
                this.AssignTemperatureControllerConfigurationGroupIdentifiers(clonedTemperatureControllerConfigurationGroup);
                dataContext.AddToTemperatureControllerConfigurationGroups(clonedTemperatureControllerConfigurationGroup);
                this.SaveTemperatureControllerConfigurationGroupData(clonedTemperatureControllerConfigurationGroup);
     
    	  . . . 
            }
     
            private EntityDataModel.TemperatureControllerConfigurationGroup Clone(EntityDataModel.TemperatureControllerConfigurationGroup configurationGroup)
            {
                EntityDataModel.TemperatureControllerConfigurationGroup clonedTemperatureControllerConfigurationGroup;
                var dataContractSerializer = new DataContractSerializer(typeof(EntityDataModel.TemperatureControllerConfigurationGroup));
     
                using (var memoryStream = new MemoryStream())
                {
                    dataContractSerializer.WriteObject(memoryStream, configurationGroup);
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    clonedTemperatureControllerConfigurationGroup = (EntityDataModel.TemperatureControllerConfigurationGroup)dataContractSerializer.ReadObject(memoryStream);
                }
     
                return clonedTemperatureControllerConfigurationGroup;
            }
     
            private void DetachTemperatureControllerConfigurationGroupObjects(EntityDataModel.TemperatureControllerConfigurationGroup configurationGroup)
            {
                foreach (var configuration in configurationGroup.TemperatureControllerConfigurations.Reverse())
                {
                    foreach (var channelConfiguration in configuration.TemperatureControllerChannelConfigurations.Reverse())
                    {
                        dataContext.Detach(channelConfiguration);
                    }
     
                    dataContext.Detach(configuration);
                }
     
                dataContext.Detach(configurationGroup);
            }
     
            private void AssignTemperatureControllerConfigurationGroupIdentifiers(EntityDataModel.TemperatureControllerConfigurationGroup configurationGroup)
            {
                var configurationGroupId = Guid.NewGuid();
     
                configurationGroup.TemperatureControllerConfigurationGroupId = configurationGroupId;
     
                foreach (var configuration in configurationGroup.TemperatureControllerConfigurations)
                {
                    var configurationId = Guid.NewGuid();
     
                    configuration.TemperatureControllerConfigurationId = configurationId;
                    configuration.TemperatureControllerConfigurationGroupId = configurationGroupId;
     
                    foreach (var channelConfiguration in configuration.TemperatureControllerChannelConfigurations)
                    {
                        channelConfiguration.TemperatureControllerChannelConfigurationId = Guid.NewGuid();
                        channelConfiguration.TemperatureControllerConfigurationId = configurationId;
                    }
                }
            }
    The line of code "dataContext.AddToTemperatureControllerConfigurationGroups(clonedTemperatureControllerConfigurationGroup);
    " generatesthe following error: "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key."
    I can't seem to figure out how the datacontext can possibly still be tracking this object. Am I missing something?
    Thanks!

     

     


    Chris
    Monday, August 29, 2011 4:02 PM

All replies

  • Hi Chris;

    When you call the Clone method it will detach the entities from the object state manager so you do not need to call DetachTemperatureControllerConfigurationGroupObjects and in fact should cause an exception to be thrown with a ObjectStateManager is not tracking this entity. Try removing the call to DetachTemperatureControllerConfigurationGroupObjects and see what happens.

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Monday, August 29, 2011 6:25 PM
  • Thank you for your input.

    I removed the line of code you suggested, but same error ("An object with the same key already exists . . . " ) is still occuring when attempting to add the cloned object to the datacontext.

    Chris


    Chris
    Monday, August 29, 2011 6:36 PM
  • Hi Chris;

    Looking over your code again you need to have the DetachTemperatureControllerConfigurationGroupObjects method in the code because it detaches the original entities from the object context so that when you do the AddToTemperatureControllerConfigurationGroups there would be no conflict when adding the cloned objects in, although not working in this case.

    If you would like to run a small test can you create a new ObjectContext and add the cloned objects to that and then update the database with the new ObjectContext. For some reason the Detach does not seem to be working and at this point I do not know why.

    If it is possible to create a small test project that shows the same error with a test database  that you could place somewhere where I can download it I will have a look from here to see what I can find.

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Monday, August 29, 2011 7:22 PM
  • Hi Fernando,

    I tried saving the cloned object to a new datacontext, but the following error was returned:

    "The object could not be added or attached because its EntityReference has an EntityKey property value that does not match the EntityKey for this object."

    I have to admit a bit of frustration with Entity Framework at this point.  I realize every technology has a learning curve, but IMO, performing a "save as" on an entity should not be quite so difficult.

    Thanks again for your help.

     

     


    Chris
    Monday, August 29, 2011 9:58 PM
  • Hi Chris;

    Well like I said your code from what I can see of it should be working and I don't know what is going on. I will do some research and if I come across anything I post here.

     


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".
    Tuesday, August 30, 2011 3:33 AM
  • Hello,

    From your description, it looks that your question may not be related to Clone itself. Like Fernandoo's said, I saw you detached TemperatureControllerConfigurationGroup entity. I suggest you check ChangeObjectState method. It looks like this.

    <your_context>.ChangeObjectState(<your_entity>, EntityState.Added)
    

    For your reference. http://msdn.microsoft.com/en-us/library/system.data.objects.objectstatemanager.changeobjectstate.aspx

    Thanks,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, August 31, 2011 2:47 AM
  • When you detach an object from the ObjectContext in preparation for cloning, you should set the detached object's EntityKey = null. Otherwise, when you reattach it, it will still have the same key and produce the duplicate key error you are seeing.
    Thursday, September 1, 2011 9:36 PM
  • Ranbla,

    I tried setting the entity keys to null but that did not resolve the issue (same error message still returned).

     	private void AssignTemperatureControllerConfigurationGroupIdentifiers(EntityDataModel.TemperatureControllerConfigurationGroup configurationGroup)
            {
                var configurationGroupId = Guid.NewGuid();
     
                configurationGroup.EntityKey = null;
                configurationGroup.TemperatureControllerConfigurationGroupId = configurationGroupId;
     
                foreach (var configuration in configurationGroup.TemperatureControllerConfigurations)
                {
                    var configurationId = Guid.NewGuid();
     
                    configuration.EntityKey = null;
                    configuration.TemperatureControllerConfigurationId = configurationId;
                    configuration.TemperatureControllerConfigurationGroupId = configurationGroupId;
     
                    foreach (var channelConfiguration in configuration.TemperatureControllerChannelConfigurations)
                    {
                        channelConfiguration.EntityKey = null;
                        channelConfiguration.TemperatureControllerChannelConfigurationId = Guid.NewGuid();
                        channelConfiguration.TemperatureControllerConfigurationId = configurationId;
                    }
                }
            }
    Thanks for the suggestion though.
    Chris

    Chris
    Friday, September 2, 2011 2:56 PM
  • Larcolais,

    Thanks for the link.  I will take a look at the ChangeObjectState method and see if that helps resolve the issue that is occuring.

    Chris


    Chris
    Friday, September 2, 2011 3:18 PM
  • Hello ChrisBZ,

    Any update from you? Was your concern solved?

    Thanks,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, September 5, 2011 1:45 AM