8

如何将实体框架对象序列化为 JavaScript 对象 (JSON)?我尝试使用JSON.NET,但是当我尝试对其进行序列化时出现以下异常。

异常:Newtonsoft.Json.JsonSerializationException,Message="自引用循环"

希特什

4

3 回答 3

7

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

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

我会确保您的对象图中只有可单向导航的引用,而不是双向导航(即仅从父级到子级,而不是从子级到父级。)那些父/子和子/父是最常见的循环引用的类型。也可能是较低级别的孩子最终引用了图的根,导致创建了一个间接循环图(然而,这些往往远不如父/子循环常见。)

一旦消除了对象图中的任何循环引用,您应该能够进行序列化。

于 2009-06-24T04:29:46.527 回答
4

我遇到了这个问题并通过将 Newtonsoft.Json.JsonIgnoreAttribute 添加到导致循环的属性来解决它。显然,该属性不会被序列化。为了帮助解决这个问题,我通常会在我的实体中同时拥有外部引用 ID 和外部类。我意识到这不是直观的(或超级棒的 OO),但这是 Julia Lerman 在她的《Programming Entity Framework: Code First》一书中推荐的方式。我发现它有助于解决 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;
    }
      ....
于 2012-04-15T18:49:23.250 回答
1

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

添加代码生成项 > 代码选项卡 > 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 
    });
于 2012-09-07T07:36:46.927 回答