EF中可序列化的类和动态代理 - 如何? [英] Serializable classes and dynamic proxies in EF - how?

查看:171
本文介绍了EF中可序列化的类和动态代理 - 如何?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

[以前发布] 中,我被设置在必须克隆的路径上我的实体我已经尝试使用序列化方法,如 [codeproject]

In [a previous posting], 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 [codeproject].

因为这些类是由Entity Framework生成的,所以我可以在这样一个自定义的.cs中单独标记它们:

because the classes are generated by Entity Framework, I mark them up separately in a custom .cs like this:

[Serializable]
public partial class Claims
{
}

但是,当检查(克隆方法):

however, when the check (in the clone method):

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

错误:

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: 

显然,我的课程声明是可序列化的,EF生成的动态代理不是...不知何故我的装饰品不会流经。

so apparently whilst my class Claims is serialisable, the dynamic proxies generated by EF are not... somehow my decorations are not flowing through.

这里有什么好处?

更新我*

更多上下文:我有一个类用户其中包含一个属性声明定义为 ICollection< Claim> 。在进行克隆时,通过的类型是集合,而不是声明 - 这就解释了克隆人为什么抱怨该类型是不可序列化的原因。所以现在的问题是:如何使 User.Claims 可序列化,因为我无法装饰属性?

for more context: I have a class User which contains a property Claims defined as an ICollection<Claim>. when doing the cloning, the type that gets passed is the collection, not Claim - this explains why the cloner is complaining that the type is not serializable. so the question now is: how do I make User.Claims serializable since I can't decorate a property?

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

*更新II *

运动的要点是设置一个深层次的副本。这是它的样子:

the point of the exercise is to facility a deep copy. this is what it looks like:

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

为了 u .Claims.Clone()工作, u.Claims 必须是可序列化的,但这不是上述原因。

in order for the u.Claims.Clone() to work, u.Claims must be serializable but it's not for the reasons cited above.

*更新III *

好的,我改变了方法,实现了这样的构造函数:

ok, I changed approach, implementing the constructor like this:

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;

现在它已经过了clone()的检查(if行),但是现在它在:

and now it gets past the clone()'s check ("if" line above), but now it breaks 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

叹息...是一切总是这么难吗?

sigh... is everything always so hard?

*更新IV *

以上是声明类有一个导航器指向用户 - 这解释了为什么上述方法指示类型为 .User _ [...] a nd意味着我不仅需要使向下的依赖性可序列化,还可以将所有路径备份起来!但是,做到这一点我成功地克隆了这个对象,但是我现在回到了原来发布的问题:

ok, so the problem above is that the Claim class has a navigator that points back to User - which explains why the above method indicates the type to be .User_[...] 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:

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。我需要一个洞头。

man. I need a hole in the head.

*更新V *

不知道问题是代理还是懒惰加载,但是在考虑了一点之后,似乎如果我通过序列化来克隆克隆,那么以前属于旧对象的东西的所有ID现在都要属于新的。我做了一个 .remove()首先在旧的对象上,如果这具有即时效果,那么也许跟踪中有一些不了解它。如果没有,那么在某个时候会有两件事情在同一个ID ...所以我开始倾向于@ Jockey的使用对象初始化器克隆的想法...

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 .remove() 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...

推荐答案

如果要序列化实体,可以在检索该对象之前禁用代理创建。如果您想要序列化它们也需要加载导航属性。

If you want to serialize entities you can disable proxy creation before retrieving that object. You also need to eager load navigational properties if you want to serialize them as well.

禁用EF 4.1中的代理创建

To disable proxy creation in EF 4.1

dbContext.Configuration.ProxyCreationEnabled = false;

在EF 4中

objectContext.ContextOptions.ProxyCreationEnabled = false;

例如:

var users = context.Users.Include("Claims").Where(/**/);

这篇关于EF中可序列化的类和动态代理 - 如何?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆