EF4 POCO WCF序列化问题(无延迟加载,代理/无代理,循环引用等) [英] EF4 POCO WCF Serialization problems (no lazy loading, proxy/no proxy, circular references, etc)

查看:124
本文介绍了EF4 POCO WCF序列化问题(无延迟加载,代理/无代理,循环引用等)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,我想确保我覆盖了我的情况,彻底尝试了一切。我很确定我需要/想要做什么,但我还没有找到成功的完美结合。



我正在利用实体框架4 RTM及其 POCO 支持。我正在寻找一个包含与其他实体(应用程序)的多对多关系的实体(Config)。我将关闭延迟加载禁用代理创建,并显式加载导航属性(通过.Include()或.LoadProperty())。但是,当加载导航属性(即给定配置加载了应用程序)时,已加载的App对象已经包含对已被带到内存的配置的引用。这将创建一个循环引用



现在我知道WCF使用的DataContractSerializer可以处理循环引用,通过设置 preserveObjectReferences 参数为true。我已经尝试过与我在网上找到的几个不同的属性实现。需要防止对象图包含循环引用,无法序列化错误。但是,它不会阻止整个图形的序列化,在Config和App之间来回。



如果我通过WcfTestClient.exe调用它,我得到一个stackoverflow (ha!)从客户端的例外,我很抱歉。我从不同的调用环境获得不同的结果(C#单元测试与本地的Web服务参考似乎工作正常,但我仍然可以不间断的在配置和应用程序之间来回滚动,但是从冷冻环境调用它只返回第一个配置列表中的错误和其他错误。)我的主要目标是从EF中显式加载图表的序列化表示(即:配置列表,每个都使用其应用程序,但没有应用程序返回到配置导航) / p>

注意:我还尝试使用ProxyDataContractResolver技术,并保持从我的上下文启用代理创建。这引起了对遇到的未知类型的抱怨。我读到ProxyDataContractResolver在Beta2中没有完全正常工作,但是应该在RTM中工作。



对于一些参考,这里大概是如何查询服务:

  var repo = BootStrapper.AppCtx [AppMeta.ConfigRepository]作为IRepository< Config> ;; 
repo.DisableLazyLoading();
repo.DisableProxyCreation();

// var temp2 = repo.Include(cfg => cfg.Apps).Where(cfg => cfg.Environment.Equals(environment))。ToArray();
var temp2 = repo.FindAll(cfg => cfg.Environment.Equals(environment))。ToArray();
foreach(var cfg in temp2)
{
repo.LoadProperty(cfg,c => c.Apps);
}

return temp2;

我认为问题的症结在于从Entity Framework 4加载POCO对象的导航属性时,它预先填充已经在内存中的对象的导航属性。尽管为处理循环引用尽了一切努力,这反过来也使WCF序列化。



我知道这是很多信息,但它真的站在我的方式在我们的系统中与EF4 / POCO一起前进。我发现了几篇关于这些话题的文章和博客,但对于我来说,我无法解决这个问题。请随时提出问题并帮助我集思广益。



PS:为了彻底,我正在注入WCF服务使用Spring.NET的HEAD构建来修复Spring.ServiceModel.Activation.ServiceHostFactory。但是,我不认为这是问题的根源。



编辑:如果我没有循环引用。 (即:我使App.Configs的设置器为私有的,这样可以防止该属性的序列化。)当它通过App对象点击Configs时,它会爆炸 - 它们似乎不被识别为与顶级配置相同的类型。



EDIT2:似乎EF或WCF不能识别实体确实相等。即:Config与特定的Config.Apps [x] .Configs [y]相同。实体键在每个模型的CSDL中正确设置,并且我已经覆盖了Equals()函数,以根据它们的Id属性对实体进行比较。这适合症状,因为没有抛出循环引用错误,但它确实是一个循环引用(并且吹出WcfTestClient.exe),并且当ProxyDataContractResolver命中Config.Apps [x] .Configs [y]'级别的配置。 (它不知道如何映射一个Config代理,ProxyDataContractResolver的工作方式不同,就像它知道如何处理初始的实体,但是它被认为是不同实体的第二级)。


哇,我可以写字对不起,你们可能想查看我的
解决方案?p = 10142rel =nofollow noreferrer>这个具体情况的博客文章 - 如果没有帮助解决您目前的困境,请给我发电子邮件!我也提供了一个示例解决方案。



请给我一些反馈,我真的很想听到更多的人关于这个特定的问题 - 特别是客户端的实现问题。


OK, I want to make sure I cover my situation and everything I've tried thoroughly. I'm pretty sure what I need/want can be done, but I haven't quite found the perfect combination for success.

I'm utilizing Entity Framework 4 RTM and its POCO support. I'm looking to query for an entity (Config) that contains a many-to-many relationship with another entity (App). I turn off lazy loading and disable proxy creation for the context and explicitly load the navigation property (either through .Include() or .LoadProperty()). However, when the navigation property is loaded (that is, Apps is loaded for a given Config), the App objects that were loaded already contain references to the Configs that have been brought to memory. This creates a circular reference.

Now I know the DataContractSerializer that WCF uses can handle circular references, by setting the preserveObjectReferences parameter to true. I've tried this with a couple of different attribute implementations I've found online. It is needed to prevent the "the object graph contains circular references and cannot be serialized" error. However, it doesn't prevent the serialization of the entire graph, back and forth between Config and App.

If I invoke it via WcfTestClient.exe, I get a stackoverflow (ha!) exception from the client and I'm hosed. I get different results from different invocation environments (C# unit test with a local reference to the web service appears to work ok though I still can drill back and forth between Configs and Apps endlessly, but calling it from a coldfusion environment only returns the first Config in the list and errors out on the others.) My main goal is to have a serialized representation of the graph I explicitly load from EF (ie: list of Configs, each with their Apps, but no App back to Config navigation.)

NOTE: I've also tried using the ProxyDataContractResolver technique and keeping the proxy creation enabled from my context. This blows up complaining about unknown types encountered. I read that the ProxyDataContractResolver didn't fully work in Beta2, but should work in RTM.

For some reference, here is roughly how I'm querying the data in the service:

var repo = BootStrapper.AppCtx["AppMeta.ConfigRepository"] as IRepository<Config>;
repo.DisableLazyLoading();
repo.DisableProxyCreation();

//var temp2 = repo.Include(cfg => cfg.Apps).Where(cfg => cfg.Environment.Equals(environment)).ToArray();
var temp2 = repo.FindAll(cfg => cfg.Environment.Equals(environment)).ToArray();
foreach (var cfg in temp2)
{
    repo.LoadProperty(cfg, c => c.Apps);
}

return temp2;

I think the crux of my problem is when loading up navigation properties for POCO objects from Entity Framework 4, it prepopulates navigation properties for objects already in memory. This in turn hoses up the WCF serialization, despite every effort made to properly handle circular references.

I know it's a lot of information, but it's really standing in my way of going forward with EF4/POCO in our system. I've found several articles and blogs touching upon these subjects, but for the life of me, I cannot resolve this issue. Feel free to simply ask questions and help me brainstorm this situation.

PS: For the sake of being thorough, I am injecting the WCF services using the HEAD build of Spring.NET for the fix to Spring.ServiceModel.Activation.ServiceHostFactory. However I don't think this is the source of the problem.

EDIT: The ProxyDataContractResolver class works correctly if I don't have the circular references. (i.e.: I make the setter of App.Configs to be private, which prevents serialization of the property.) It blows up, it appears, when it hits Configs via the App object -- they don't seem to be recognized as the same type as the top level Configs.

EDIT2: It appears that either EF or WCF doesn't recognize that the entities are indeed equal. i.e.: 'Config' is the same as a particular 'Config.Apps[x].Configs[y]'. The entity keys are properly set in the CSDL for each model and I've overridden the Equals() function to compare entities based on their 'Id' property. This fits the symptoms as no circular reference error is thrown, yet it is indeed a circular reference (and blows up WcfTestClient.exe) AND the ProxyDataContractResolver blows up when it hits the 'Config.Apps[x].Configs[y]' level of Configs. (It doesn't know how to map a Config proxy. The ProxyDataContractResolver works otherwise. It's like it knows how to handle the initial round of entities, but the second level it considers as different entities.)

Wow, I can be wordy. Sorry folks!

解决方案

You might want to check out my blog post on this specific scenario - please email me if it doesn't help fix your current predicament! I've included a sample solution as well.

Please drop me some feedback either way, I'd really like to hear from more people on this particular issue - especially with the implementation problems on the client end of things.

这篇关于EF4 POCO WCF序列化问题(无延迟加载,代理/无代理,循环引用等)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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