title: Using Serialization to copy entities between two ObjectContexts in Entity Framework
body: <h2>Preface</h2>
  
  <p>I know this is probably already regarded as <a href="https://stackoverflow.com/q/6925028/1426433"><strong>crazy question</strong></a>, but I am looking for the most educated advice and <strong>PROVEN</strong> recommendation on how to proceed with copying <strong>ALL</strong> data (i.e., all entities and relationships) from an <code>ObjectContext</code> to a newly created <code>ObjectContext</code> backed in a different store. <strong>See <a href="https://stackoverflow.com/q/12589017/1426433">&quot;Cloning&quot; EntityConnections and ObjectContexts in Entity Framework</a> to check out how I'm setting this up.</strong></p>
  
  <hr>
  
  <h2>Intro</h2>
  
  <p><strong>I've seen <a href="https://stackoverflow.com/q/2185155/1426433">Cloning data on Entity Framework</a>,</strong> but:</p>
  
  <ol>
  <li><p>I'm looking for <strong>the whole enchilada</strong>, i.e., the whole object graph: all entities &amp; relationships. Later on, I'll go for a more fined-grained selection of what parts of the object graph)</p></li>
  <li><p>As per my updates below, I haven't made serialization to work, but only on special cases. I feels like it really be a not-so-complex task, but it's been surprisingly challenging. I definitely need some insight on how to make it work.</p></li>
  </ol>
  
  <hr>
  
  <h2>Step 1</h2>
  
  <p>OK, this is what I've tried so far. </p>
  
  <p>I am aware that when I use the <code>Detach</code>/<code>Attach</code> power duo, relationships are kaput—<strong>and I ACTUALLY want to preserve the whole object graph.</strong></p>
  
  <p>Therefore, I was thinking of loading the root entities with the <code>MergeOption.NoTracking</code> option:</p>
  
  <pre><code>var serializer = new DataContractSerializer(typeof(Root));
  
  var query = (ObjectQuery&lt;Root&gt;) sourceContext.Roots
      .Include(d =&gt; d.Children.Select(c =&gt; c.MoreChildren.Select(r =&gt; r.EvenMoreChildren)))
      .Include(d =&gt; d.Children.Select(c =&gt; c.MoreChildren.Select(r =&gt; r.MoreAndMoreChildren)))
      .Include(d =&gt; d.Children.Select(c =&gt; c.MoreChildren.Select(r =&gt; r.Shizzle)));
  
  foreach (var d in query.Execute(MergeOption.NoTracking)) {
      //sourceContext.Detach(d); // not needed
      Print(d);
      using (var ios = new MemoryStream()) {
          serializer.WriteObject(ios, d);
          ios.Seek(0, SeekOrigin.Begin);
          var dd = (Root) serializer.ReadObject(ios);
          //Console.WriteLine(string.Join(",", dd.EntityKey.EntityKeyValues.Select(k =&gt; k.Key + "=" + k.Value)));
          targetContext.Roots.AddObject(dd);
      }
  }
  </code></pre>
  
  <p>Given that I am loading entities as non-tracked, the I don't need to call <code>sourceContext.Detach(d)</code> anymore.</p>
  
  <p>The <code>Print</code> method simply prints the child-object tree, and it shows that up to that point things are going well (I won't show it here cuz it's huge and irrelevant).</p>
  
  <p>However, now the whole thing is blowing @ <code>serializer.WriteObject(ios, d)</code> with the following message:</p>
  
  <p><strong>"When an object is returned with a <code>NoTracking</code> merge option, Load can only be called when the <code>EntityCollection</code> or <code>EntityReference</code> does not contain objects."</strong></p>
  
  <p>(Which kinda makes sense, because the serializer is probably trying to lazy load related entities.)</p>
  
  <p>Remember, if I don't use <code>NoTracking</code>, I have to detach the entities but then I would lose my relationships...</p>
  
  <hr>
  
  <h2>Step 2</h2>
  
  <p>Of course I've tried setting <code>sourceContext.ContextOptions.LazyLoadingEnabled = false</code> just before executing the serializing loop, and that fixes the error above, but that results in the infamous:</p>
  
  <p><strong>"The object could not be added or attached because its <code>EntityReference</code> has an <code>EntityKey</code> property value that does not match the <code>EntityKey</code> for this object."</strong></p>
  
  <p>Also, remember I still cannot uncomment the <code>sourceContext.Detach(d)</code> since I loaded the roots with <code>NoTracking</code>...</p>
  
  <hr>
  
  <h2>Step 3</h2>
  
  <p>I've tried setting the <code>EntityKey = null</code> before serialization and even after deserialization on the cloned entity... all to no avail:</p>
  
  <pre><code>sourceContext.ContextOptions.LazyLoadingEnabled = false;
  
  foreach (var d in query.Execute(MergeOption.NoTracking)) {
      //sourceContext.Detach(d);
      Print(d);
      d.EntityKey = null;
      using (var ios = new MemoryStream()) {
          serializer.WriteObject(ios, d);
          ios.Seek(0, SeekOrigin.Begin);
          var dd = (Root) serializer.ReadObject(ios);
          if (dd.EntityKey != null) {
              Console.WriteLine("Deserialized EntityKey: {0}", string.Join(",", dd.EntityKey.EntityKeyValues.Select(k =&gt; k.Key + "=" + k.Value)));
              dd.EntityKey = null;
          }
          targetContext.Roots.AddObject(dd);
      }
  }
  </code></pre>
  
  <p><strong>What's fishy is that I don't even know what bloody "object" is the exception above talking about.</strong></p>
  
  <p>Am I really, really, really, really DOOMED in my attempt to have a purely EF approach to solve this problem???</p>
  
  <p>Am I completely DOOMED?!?!?! :(</p>