获得JSON序列化实体框架自我参照环路误差即使ProxyCreation假使用显式时包括 [英] Getting JSON Serialization Entity Framework Self Reference Loop error even after ProxyCreation false when using explicit Include

查看:198
本文介绍了获得JSON序列化实体框架自我参照环路误差即使ProxyCreation假使用显式时包括的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JSON序列化(ASP.Net的Web API)失败,因为自引用循环(这是一个普遍的问题,原因是:被请求的实体延迟加载子实体和每一个孩子都有一个反向引用父实体)的。

我周围的工作中发现,但并不能帮助我:


  1. Use [JsonIgnore]为导航属性被忽略:
    此解决方案但对我来说并不适用。例如:要获得他的命令​​沿着一条客户信息,我会很快在Order类中添加[JsonIgnore]以顾客财产,但是当我要与客户详细信息相处订单信息,因为有[JsonIgnore]对顾客财产,它不会包括顾客的信息。

  2. 更改JSON.Net串行器设置为preserve 的参考:
    不能preserve因为我不需要循环引用的数据。

  3. 禁用代理创建的数据上下文和使用明确的加载(这应该理想地解决这个问题)
    禁用代理的创建停止延迟加载和返回数据没有错误,但是当我明确包括子实体,我再次得到了意外自引用循环错误!的错误是在背参考电平父实体。

沿着相同的路线任何经验/建议?


解决方案

我尝试了所有建议的解决方案,但没有奏效。与重写JSON.Net串行的DefaultContractResolver这结束了:

 公共类FilterContractResolver:DefaultContractResolver
{
    字典<类型,列表与LT;串GT;> _propertiesToIgnore;    公共FilterContractResolver(词典<类型,列表与LT;串GT;> propertiesToIgnore)
    {
        _propertiesToIgnore = propertiesToIgnore;
    }    保护覆盖JsonProperty CreateProperty(的MemberInfo成员,MemberSerialization memberSerialization)
    {
        VAR财产= base.CreateProperty(成员,memberSerialization);
        清单<串GT;忽略;
        property.Ignored | =((_propertiesToIgnore.TryGetValue(member.DeclaringType,出toIgnore)|| _propertiesToIgnore.TryGetValue(member.DeclaringType.BaseType,出toIgnore))及和放大器; toIgnore.Contains(property.PropertyName));
        返回财产;
    }
}

然后创建一个静态类返回属性的字典被忽略基于控制器:

 公共静态类CriteriaDefination
{
    私有静态字典<字符串,字典<类型,列表与LT;串GT;>> ToIgnore =新词典<字符串,字典<类型,列表与LT;串GT;>>
    {
        {
            tblCustomer,新的字典<类型,列表与LT;串GT;> {
                {
                    typeof运算(tblCustomer),新的List<串GT; {
                        //包括所有
                    }
                },
                {
                    typeof运算(tblOrder),新的List<串GT; {
                        tblCustomer//忽略回参考tblCustomer
                    }
                }
            }
        },
        {
            tblOrder,新的字典<类型,列表与LT;串GT;> {
                {
                    typeof运算(tblCustomer),新的List<串GT; {
                        tblOrders//忽略回参考tblOrders
                    }
                },
                {
                    typeof运算(tblOrder),新的List<串GT; {
                        //包括所有
                    }
                }
            }
        }
    };
    公共静态字典<类型,列表与LT;串GT;> IgnoreList(字符串键)
    {
        返回ToIgnore [关键]
    }
}

和每一个控制器内改变JSON格式程序是这样的:

<$p$p><$c$c>GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver =新FilterContractResolver(CriteriaDefination.IgnoreList(tblCustomer));

JSON Serialization (ASP.Net Web API) fails because of self-referencing loop (it’s a common problem, Reason: an entity being requested lazy loads child entities and every child has a back reference to parent entity).

Work around I found, but doesn’t help me:

  1. Use [JsonIgnore] for navigation properties to be ignored: This solution works but doesn’t apply in my case. For Example: To get a Customer information along with his Orders, I would quickly add [JsonIgnore] to Customer property in Order class, but when I want to get an Order information along with the Customer details, since there’s [JsonIgnore] on Customer property, it won’t include Customer details.
  2. Change JSON.Net Serializer Settings to Preserve References: Can’t Preserve because I don’t need Circular referenced data.
  3. Disable Proxy Creation at the Data Context and use explicit loading(this should ideally solve the problem): Disabling proxy creation stops Lazy Loading and returns data without error, but when I explicitly Include child entities, I again the get the unexpected self-referencing loop error! The error is at the back-reference level to parent entity.

Any experiences along the same lines/suggestions?

解决方案

I tried all the suggested solutions but didn't work. Ended up with Overriding the JSON.Net Serializer’s DefaultContractResolver to this:

public class FilterContractResolver : DefaultContractResolver
{
    Dictionary<Type, List<string>> _propertiesToIgnore;

    public FilterContractResolver(Dictionary<Type, List<string>> propertiesToIgnore)
    {
        _propertiesToIgnore = propertiesToIgnore;
    }

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        List<string> toIgnore;
        property.Ignored |= ((_propertiesToIgnore.TryGetValue(member.DeclaringType, out toIgnore) || _propertiesToIgnore.TryGetValue(member.DeclaringType.BaseType, out toIgnore)) && toIgnore.Contains(property.PropertyName));
        return property;
    }
}

Then created a Static Class which returns a dictionary of Properties to be Ignored based on the Controller:

public static class CriteriaDefination
{
    private static Dictionary<string, Dictionary<Type, List<string>>> ToIgnore = new Dictionary<string, Dictionary<Type, List<string>>>
    {
        {
            "tblCustomer", new Dictionary<Type, List<string>>{
                {
                    typeof(tblCustomer), new List<string>{
                        //include all
                    }
                },
                {
                    typeof(tblOrder), new List<string>{
                        "tblCustomer"//ignore back reference to tblCustomer
                    }
                }
            }
        },
        {
            "tblOrder", new Dictionary<Type, List<string>>{
                {
                    typeof(tblCustomer), new List<string>{
                        "tblOrders"//ignore back reference to tblOrders
                    }
                },
                {
                    typeof(tblOrder), new List<string>{
                        //include all
                    }
                }
            }
        }
    };
    public static Dictionary<Type, List<string>> IgnoreList(string key)
    {
        return ToIgnore[key];
    }
}

And inside every controller change the JSON Formatter something like:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new FilterContractResolver(CriteriaDefination.IgnoreList("tblCustomer"));

这篇关于获得JSON序列化实体框架自我参照环路误差即使ProxyCreation假使用显式时包括的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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