title: Serializable classes and dynamic proxies in EF - how?
body: <p>In <a href="https://stackoverflow.com/questions/7266848/downcasting-with-entity-framework">[a previous posting]</a>, I was set on the path to having to clone my entities.  This I've attempted to do with a serialisation approach as found in <a href="http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx" rel="nofollow noreferrer">[codeproject]</a>.</p>
  
  <p>because the classes are generated by Entity Framework, I mark them up separately in a custom .cs like this:</p>
  
  <pre><code>[Serializable]
  public partial class Claims
  {
  }
  </code></pre>
  
  <p>however, when the check (in the clone method):</p>
  
  <pre><code>if (Object.ReferenceEquals(source, null))
  {
  </code></pre>
  
  <p>gets hit, I get the error:</p>
  
  <pre><code>System.ArgumentException was unhandled by user code
    Message=The type must be serializable.
  Parameter name: source
    Source=Web
    ParamName=source
    StackTrace:
         at .Web.Cloner.Clone[T](T source) in C:\Users\.\Documents\Visual Studio 2010\Projects\.\Website\Extensions.Object.cs:line 49
         at .Web.Models.Employer..ctor(User u) in C:\Users\.\Documents\Visual Studio 2010\Projects\.\Website\Models\EF.Custom.cs:line 121
         at .Web.Controllers.AuthController.Register(String Company, String GivenName, String Surname, String Title, String Department) in C:\Users\.\Documents\Visual Studio 2010\Projects\.\Website\Controllers\AuthController.cs:line 119
         at lambda_method(Closure , ControllerBase , Object[] )
         at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
         at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
         at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
         at System.Web.Mvc.ControllerActionInvoker.&lt;&gt;c__DisplayClass15.&lt;InvokeActionMethodWithFilters&gt;b__12()
         at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
    InnerException: 
  </code></pre>
  
  <p>so apparently whilst my class <code>Claims</code> is serialisable, the dynamic proxies generated by EF are not... somehow my decorations are not flowing through.</p>
  
  <p>what's the trick here?</p>
  
  <p><strong>* Update I *</strong></p>
  
  <p>for more context: I have a class <code>User</code> which contains a property <code>Claims</code> defined as an <code>ICollection&lt;Claim&gt;</code>.  when doing the cloning, the type that gets passed is the collection, not <code>Claim</code> - this explains why the cloner is complaining that the type is not serializable.  so the question now is: how do I make <code>User.Claims</code> serializable since I can't decorate a property?</p>
  
  <pre><code>Error   1   Attribute 'Serializable' is not valid on this declaration type.
  It is only valid on 'class, struct, enum, delegate' declarations.   
  C:\Users\.\Documents\Visual Studio 2010\Projects\.\Website\Models\EF.Custom.cs
  128 10  Website
  </code></pre>
  
  <p><strong>* Update II *</strong></p>
  
  <p>the point of the exercise is to facility a deep copy.  this is what it looks like:</p>
  
  <pre><code>public partial class Employer
  {
      public Employer(User u)
      {
          this.Id = u.Id;
          this.GivenName = u.GivenName;
          this.Surname = u.Surname;
          this.Claims = u.Claims.Clone();
          this.Contacts = u.Contacts.Clone();
      }
  }
  </code></pre>
  
  <p>in order for the <code>u.Claims.Clone()</code> to work, <code>u.Claims</code> must be serializable but it's not for the reasons cited above.</p>
  
  <p><strong>* Update III *</strong></p>
  
  <p>ok, I changed approach, implementing the constructor like this:</p>
  
  <pre><code>public partial class Employer
  {
      public Employer(User u)
      {
          this.Id = u.Id;
          this.GivenName = u.GivenName;
          this.Surname = u.Surname;
  
          ICollection&lt;Claim&gt; cs = new List&lt;Claim&gt;();
          foreach (Claim c in u.Claims)
          {
              cs.Add(c.Clone());
          }
          this.Claims = cs;
  </code></pre>
  
  <p>and now it gets past the clone()'s check ("if" line above), but now it breaks at:</p>
  
  <pre><code>formatter.Serialize(stream, source);
  </code></pre>
  
  <p>with:</p>
  
  <pre><code>System.Runtime.Serialization.SerializationException was unhandled by user code
    Message=Type 'System.Data.Entity.DynamicProxies.User_7B7AFFFE306AB2E39C07D91CC157792F503F36DFCAB490FB3333A52EA1D5DC0D' in Assembly 'EntityFrameworkDynamicProxies-Web, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' is not marked as serializable.
    Source=mscorlib
    StackTrace:
         at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
         at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
         at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
         at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder)
         at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
         at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
         at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
         at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph)
         at Skillscore.Web.Cloner.Clone[T](T source) in C:\Users\.\Documents\Visual Studio 2010\Projects\.\Website\Extensions.Object.cs:line 62
         at Skillscore.Web.Models.Employer..ctor(User u) in C:\Users\.\Documents\Visual Studio 2010\Projects\.\Website\Models\EF.Custom.cs:line 130
  </code></pre>
  
  <p>sigh... is everything always so hard?</p>
  
  <p><strong>* Update IV *</strong></p>
  
  <p>ok, so the problem above is that the <code>Claim</code> class has a navigator that points back to <code>User</code> - which explains why the above method indicates the type to be <code>.User_[...]</code> and implies I need to not only make the downward dependencies serializable, but also all of the paths back up!  However, having done that I successfully clone the object but I'm now back to the issue in my original posting:</p>
  
  <pre><code>System.InvalidOperationException was unhandled by user code
    Message=Conflicting changes to the role 'User' of the relationship 'EF.ClaimUser' have been detected.
    Source=System.Data.Entity
    StackTrace:
         at System.Data.Objects.DataClasses.RelatedEnd.IncludeEntity(IEntityWrapper wrappedEntity, Boolean addRelationshipAsUnchanged, Boolean doAttach)
         at System.Data.Objects.DataClasses.EntityCollection`1.Include(Boolean addRelationshipAsUnchanged, Boolean doAttach)
         at System.Data.Objects.DataClasses.RelationshipManager.AddRelatedEntitiesToObjectStateManager(Boolean doAttach)
         at System.Data.Objects.ObjectContext.AddObject(String entitySetName, Object entity)
         at System.Data.Entity.Internal.Linq.InternalSet`1.&lt;&gt;c__DisplayClass5.&lt;Add&gt;b__4()
         at System.Data.Entity.Internal.Linq.InternalSet`1.ActOnSet(Action action, EntityState newState, Object entity, String methodName)
         at System.Data.Entity.Internal.Linq.InternalSet`1.Add(Object entity)
         at System.Data.Entity.DbSet`1.Add(TEntity entity)
         at Skillscore.Web.Controllers.AuthController.Register(String Company, String GivenName, String Surname, String Title, String Department) in C:\Users\.\Documents\Visual Studio 2010\Projects\.\Website\Controllers\AuthController.cs:line 138
  </code></pre>
  
  <p>man.  I need a hole in the head.</p>
  
  <p><strong>* Update V *</strong></p>
  
  <p>I don't know if the issue is the proxies or lazy loading, but after thinking about it a little, it seems that if I do a clone via serialisation, all the IDs for things that used to belong to the old object are now going to belong to the new one.  I did do a <code>.remove()</code> first on the old object and if that has immediate effect then maybe there's something in the tracking that doesn't know about it.  If it doesn't, then at one point there will be two things out there with the same ID... so I'm starting to lean towards @Jockey's idea of using object initialisers for the cloning...</p>