Ofe*_*lig 4 jsonserializer entity-framework-4 self-tracking-entities c#-4.0 servicestack
我想将一个实体框架自我跟踪实体完整对象图(一对多关系中的父/子)序列化为Json.
为了序列化我使用ServiceStack.JsonSerializer.
这就是我的数据库的样子(为简单起见,我删除了所有不相关的字段):
我以这种方式获取完整的个人资料图:
public Profile GetUserProfile(Guid userID)
{
using (var db = new AcmeEntities())
{
return db.Profiles.Include("ProfileImages").Single(p => p.UserId == userId);
}
}
Run Code Online (Sandbox Code Playgroud)
问题是尝试序列化它:
Profile profile = GetUserProfile(userId);
ServiceStack.JsonSerializer.SerializeToString(profile);
Run Code Online (Sandbox Code Playgroud)
生产一个StackOverflowException
.我相信这是因为EF提供了一个无限模型,可以将串行器拧紧.也就是说,我可以称之为:profile.ProfileImages[0].Profile.ProfileImages[0].Profile ...
等等.
如何"展平"我的EF对象图或以其他方式阻止ServiceStack.JsonSerializer进入堆栈溢出情况?
您有一些相互矛盾的问题,EF模型已经过优化,可以将您的数据模型存储在RDBMS中,而不是用于序列化 - 这是具有单独DTO的角色.否则,您的客户端将绑定到您的数据库,您的数据模型上的每个更改都有可能破坏您现有的服务客户端.
话虽如此,正确的做法是维护您映射到的单独DTO,这些DTO定义了您希望模型从外部世界看起来的所需形状(也称为线格式).
ServiceStack.Common包含内置映射函数(即TranslateTo/PopulateFrom),可简化将实体映射到DTO,反之亦然.这是一个显示这个的例子:
https://groups.google.com/d/msg/servicestack/BF-egdVm3M8/0DXLIeDoVJEJ
另一种方法是使用[DataContract]/[DataMember]字段装饰要在数据模型上序列化的字段.任何未归属于[DataMember]的属性都不会被序列化 - 因此您可以使用它来隐藏导致StackOverflowException的循环引用.
为了我的同伴StackOverflowers进入这个问题,我将解释我最终做了什么:
在我所描述的情况,你必须使用标准的.NET序列化(而不是ServiceStack的)System.Web.Script.Serialization.JavaScriptSerializer
.原因是您可以修饰不希望序列化程序在[ScriptIgnore]
属性中处理的导航属性.
顺便说一句,您仍然可以ServiceStack.JsonSerializer
用于反序列化 - 它比.NET快,并且您没有我问过这个问题的StackOverflowException问题.
另一个问题是如何使自我跟踪实体装饰相关的导航属性[ScriptIgnore]
.
说明:如果没有
[ScriptIgnore]
,序列化(使用.NET Javascript序列化程序)也会引发一个关于循环引用的异常(类似于在ServiceStack中引发StackOverflowException的问题).我们需要消除循环性,这是使用完成的[ScriptIgnore]
.
所以我编辑了ADO.NET自我跟踪实体生成器模板.TT
附带的文件,并将其设置为包含在相关位置(如果有人想要代码差异,请给我写评论).有人说编辑这些"外部",不是意味着要编辑的文件是一种不好的做法,但是哎呀 - 它解决了这个问题,这是唯一不会迫使我重新构建整个问题的方法.应用(使用POCO代替STE,将DTO用于所有等)[ScriptIgnore]
@mythz:我不完全赞同你关于使用DTO的争论 - 请看你对你的答案的评论.我非常感谢您为构建ServiceStack(所有模块!)并使其免费使用和开源所付出的巨大努力.我只是鼓励您尊重文本序列化程序中的[ScriptIgnore]属性,或者提出您的属性.否则,即使实际上可以使用DTO,它们也无法将子对象的导航属性添加回父对象,因为它们将获得StackOverflowException.我确实将你的答案标记为"已接受",因为毕竟它帮助我找到了解决这个问题的方法.
归档时间: |
|
查看次数: |
13262 次 |
最近记录: |