【问题标题】:json.net; serialize entity framework object (circular reference error)json.net;序列化实体框架对象(循环引用错误)
【发布时间】:2011-12-20 11:18:11
【问题描述】:

我有一个实体框架实体,我想将其序列化为 json 对象。我环顾四周,发现 json.net (http://james.newtonking.com/projects/json-net.aspx) 应该能够使用“开箱即用”的循环引用序列化对象。所以我尝试使用

string json = JsonConvert.SerializeObject(/* my ef entity */);

但我仍然遇到同样的错误。问题可能是我需要使用ReferenceLoopHandling.IgnoreContractResolver,但我不确定如何使用它们。任何帮助深表感谢!谢谢

【问题讨论】:

  • @CraigStuntz 不,因为我不想将属性手动映射到新对象上。我在问如何使用 JSON.NET 来做到这一点
  • 建议的解决方案适用于 JSON.NET。如果您真的更愿意处理循环引用而不是赋值语句,那么这取决于您。但 JSON.NET 并不意味着其他解决方案不起作用。
  • @CraigStuntz 我不需要 json.net 手动将值映射到新对象。

标签: c# asp.net entity-framework json.net


【解决方案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 
    });

【讨论】:

    【解决方案2】:

    另一种解决方案是将[JsonIgnore] 属性添加到您的导航属性中。

    例如:

    using System;
    using System.ComponentModel.DataAnnotations.Schema;
    
    [Serializable]
    public class Entity
    {
        public int EntityID { get; set; }
        public string EntityName { get; set; }
    
        [JsonIgnore]
        public virtual Parent Parent { get; set; }
        [JsonIgnore]
        public virtual List<Child> Children { get; set; }
    }
    

    【讨论】:

    • 这是正确的答案,实体应该相互引用。但是您需要忽略子实体中的主实体属性。
    • 但是如果我想从子元素的角度来查看关系呢?
    • 你成就了我的一天
    • 谢谢,我认为这是最好的解决方案。
    【解决方案3】:

    我使用以下解决方案来克隆我的实体,没有任何技巧需要关于实体上的数据属性和我的表循环引用得到保留。我什至有实体相互指向而没有任何问题。 序列化所需的库是 Json.Net(Newtonsoft.Json dll)。

        private static T CloneObject<T>(T obj)
        {
            if (obj == null)
                return obj;
            string ser = JsonConvert.SerializeObject(obj, Formatting.Indented, 
                new JsonSerializerSettings() {
                                    NullValueHandling = NullValueHandling.Ignore,
                                    MissingMemberHandling = MissingMemberHandling.Ignore,
                                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore});
            return (T) JsonConvert.DeserializeObject(ser, obj.GetType());
        }
    

    示例用法:

        protected object CopyObj(Object obj)
        {
            return CloneObject(obj);
        }
        var cust1 = this.cts.Customers().Where(cc => cc.Id == 3).Include(cc => cc.Addresses).FirstOrDefault();
        var cust2 = CopyObj(cust1) as Customers;  
        //Cust2 now includes copies of the customer record and its addresses
    

    【讨论】:

      【解决方案4】:

      我的解决方案是简单地删除子实体上的父引用。

      所以在我的模型中,我选择了关系并将父引用更改为内部而不是公共。

      可能不是所有人的理想解决方案,但对我有用。

      【讨论】:

        【解决方案5】:

        试试这个:首先确保 poco 或模型具有 DataContract、DataMemeber 并删除虚拟关键字..然后..

         public string Get()
            {
                var list = _languageRepository.GetMany(l => l.LanguageTrans.FirstOrDefault().CultureCode == "en").ToList();
        
                string json = JsonConvert.SerializeObject(list, Formatting.Indented, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects });
        
                return json;
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-05-25
          • 1970-01-01
          • 2019-12-08
          • 1970-01-01
          • 2017-07-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多