使用Json.Net序列化实体框架对象

时间:2009-06-24 04:20:49

标签: javascript asp.net-mvc entity-framework json.net

如何将实体框架对象序列化为JavaScript Object(JSON)?我尝试使用JSON.NET,但在尝试序列化时遇到以下异常。

异常:Newtonsoft.Json.JsonSerializationException,Message =“Self referencing loop”

Hitesh

3 个答案:

答案 0 :(得分:7)

在循环引用方面,听起来您遇到与原始DataContract序列化程序相同的一般问题。虽然相互引用的对象与内存中的对象图相当常见,但如果序列化程序没有特别考虑它,则这种循环引用在序列化时不可避免地会导致无限递归。在常见的非二进制序列化格式(XML和JSON是最常见的两种格式)中,很少有(如果有的话)建立标准来处理循环引用。

Microsoft通过在xml中使用ref语义解决了.NET 3.5 SP1中DataContract序列化程序的循环问题。据我所知,JSON没有这样的东西,这可能就是JSON.NET阻止你序列化对象图形的原因。

我会确保你的对象图中只有可以单向导航的引用,而不是两种方式(即只从父对子,而不是从子到父。)那些父/子和子/父是最常见的循环引用类型。也可能是较低级别的子级最终引用图形的根,导致创建间接循环图(但这些图形往往远不如父/子循环那么常见。)

在对象图中消除任何循环引用后,您应该能够序列化。

答案 1 :(得分:4)

我遇到了这个问题并通过将Newtonsoft.Json.JsonIgnoreAttribute添加到导致循环的属性来解决了这个问题。显然,该属性不会被序列化。为了解决这个问题,我通常会在我的实体中同时拥有外部引用ID和外部类。我意识到这不是直观的(或超级优秀的OO),但它是Julia Lerman在她的“编程实体框架:代码优先”一书中推荐的方式。我发现它有助于消除Entity Framework的几个问题。

 public class SomeEntity
 {
      [JsonIgnore]
      public ForeignEntity SomeForeignEntity {get;set;}
      public Guid ForeignEntityId {get;set;}
 }

更新:我忘了提及我还需要在DbContext上禁用代理,如下所示:

dataContext.Configuration.ProxyCreationEnabled = false;

如果您正在编写服务的代码(如果您正在序列化,这似乎很可能),那么这可能不是问题,但是在禁用代理创建时会丢失一些内容。有关更多详细信息,请参见此处:http://www.sellsbrothers.com/posts/Details/12665

我正在使用MS Web Api,因此我只是在构建控制器时禁用代理创建:

public class MailingApiController : ApiController
{
    public MailingApiController()
    {
        PreventDeepSerialization();
    }

    private static void PreventDeepSerialization()
    {
        var dataContext = Injector.Get<IIntertwyneDbContext>();
        dataContext.Configuration.ProxyCreationEnabled = false;
    }
      ....

答案 2 :(得分:1)

为了解决这个问题,我将我的实体转换为基于POCO的Code First。要执行此操作,请在edmx窗口中右键单击并选择:

添加代码生成项&gt;代码标签&gt; EF POCO实体生成器。

请注意,如果您没有看到它,可能需要使用nuget进行安装。

在运行时,EF会将代理类添加到这些对象以进行跟踪,但它们往往会搞乱序列化过程。为了防止这种情况,我们可以简单地将ProxyCreationEnabled设置为false,如下所示:

var context = new YourEntities();
context.Configuration.ProxyCreationEnabled = false;

var results = context.YourEntity.Take(100).ToList();

然后,您可以通过省略默认引用循环来安全地返回JSON.NET序列化数据,如下所示:

return JsonConvert.SerializeObject(results, Formatting.Indented, 
    new jsonSerializerSettings { 
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
    });