How do I use serializable classes and dynamic proxies in EF?

asp.net-mvc-3 c# clone entity-framework serialization

Question

I was put on the road of needing to clone my entities in an earlier posting. This is what I've tried to do using a serialization strategy outlined in [codeproject].

Since Entity Framework generates the classes, I mark them up uniquely in a custom.cs file as follows:

[Serializable]
public partial class Claims
{
}

However, when the clone method checks:

if (Object.ReferenceEquals(source, null))
{

hits, I experience the error:

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.<>c__DisplayClass15.<InvokeActionMethodWithFilters>b__12()
       at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
  InnerException: 

evidently, during my classClaims is serializable, but the dynamic proxies created by EF are not; this is why my decorations aren't working.

What's going on here?

Updating I

further context: I'm in a class.User it has a characteristicClaims seen as anICollection<Claim> . The collection is the type that is passed when cloning, notClaim Because of this, it is clear why the cloner complains that the type cannot be serialized. so, the current query is: How can I createUser.Claims Since I cannot decorate a property, is it serializable?

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

Update No. II

The exercise's goal is to facilitate a deep copy. This is how it appears:

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();
    }
}

to enable theu.Claims.Clone() a job,u.Claims must be serializable, but for the reasons stated above, it is not.

* Third Update *

Okay, I took a different approach and implemented the constructor as follows:

public partial class Employer
{
    public Employer(User u)
    {
        this.Id = u.Id;
        this.GivenName = u.GivenName;
        this.Surname = u.Surname;

        ICollection<Claim> cs = new List<Claim>();
        foreach (Claim c in u.Claims)
        {
            cs.Add(c.Clone());
        }
        this.Claims = cs;

and after passing the clone() check (see the "if" line above), it now fails at:

formatter.Serialize(stream, source);

with:

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

Is everything always so challenging?

update four

Okay, however, the issue is that theClaim class has a backwards-pointing navigator.User - This explains why the approach described above suggests that the type is.User_[...] That means that I must serialize not just all of the pathways back up, but also the downward dependencies! But after doing so, I was able to duplicate the object, thus I'm back to the problem I raised in my first posting:

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.<>c__DisplayClass5.<Add>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

Man, I need a brain-sized hole.

* Version V *

I'm not sure whether the problem is with the proxies or lazy loading, but after some consideration, it appears that if I do a serialization clone, all the IDs for items that previously belonged to the old object will now be associated with the new one. I completed a.remove() first on the old object; if that has an instant impact, maybe there is a tracking component that is unaware of it. If not, there will eventually be two items with the same ID in existence. As a result, I'm beginning to favor @Jockey's suggestion to use object initializers for the cloning.

1
21
5/23/2017 12:33:54 PM

Popular Answer

Before getting that object, you may deactivate proxy creation if you wish to serialize entities. If you wish to serialize navigational properties as well, you must eager load them as well.

To prevent EF 4.1 from creating proxies

dbContext.Configuration.ProxyCreationEnabled = false;

In EF 4

objectContext.ContextOptions.ProxyCreationEnabled = false;

eg:

var users = context.Users.Include("Claims").Where(/**/);
35
9/1/2011 11:46:54 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow