获取JSON序列化实体框架自我引用即使在ProxyCreation之后循环错误,当使用显式包含时为false [英] Getting JSON Serialization Entity Framework Self Reference Loop error even after ProxyCreation false when using explicit Include

查看:142
本文介绍了获取JSON序列化实体框架自我引用即使在ProxyCreation之后循环错误,当使用显式包含时为false的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

JSON序列化(ASP.Net Web API)因为自引用循环而失败(这是一个常见的问题,原因是:被请求的实体懒惰加载子实体,每个子项都有对父实体的反引用)。 >

我找到了,但不帮助我:


  1. 使用[JsonIgnore]导航属性将被忽略:
    这个解决方案是有效的,但不适用于我的情况。例如:要获得客户信息以及其订单,我可以在订单类中快速添加[JsonIgnore]到Customer属性,但是当我想要获得订单信息以及客户详细信息时,由于客户属性[JsonIgnore] ,它不会包括客户详细信息。

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

  3. 禁用代理创建在数据上下文并使用显式加载(这应该理想地解决问题)
    禁用代理创建停止Lazy加载并返回数据没有错误但是当我显式包括子实体,我再次得到意想不到的自我引用循环错误!错误在父实体的反向参考级别。



<任何相同线条的经验uggestions?

解决方案

我尝试了所有建议的解决方案,但没有工作。结束语将JSON.Net Serializer的DefaultContractResolver覆盖到:

  public class FilterContractResolver:DefaultContractResolver 
{
字典<类型,列表< 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);
列表< string>忽略;
property.Ignored | =((_propertiesToIgnore.TryGetValue(member.DeclaringType,out toIgnore)|| _propertiesToIgnore.TryGetValue(member.DeclaringType.BaseType,out toIgnore))&& toIgnore.Contains(property.PropertyName) );
返回属性;
}
}

然后创建一个静态类,返回属性的字典根据控制器忽略:

  public static class CriteriaDefination 
{
private static Dictionary< string ,字典<类型,列表< string>>> ToIgnore = new Dictionary< string,Dictionary< Type,List< string>>>
{
{
tblCustomer,新字典< Type,List< string>> {
{
typeof(tblCustomer),new List< string> {
//包括所有
}
},
{
typeof(tblOrder),新列表< string> {
tblCustomer//忽略回参考tblCustomer
}
}
}
},
{
tblOrder,新字典< Type,List< string>> {
{
typeof(tblCustomer),新列表< string> {
tblOrders//忽略对tblOrders的引用
}
},
{
typeof(tblOrder),新列表< string> {
// include all
}
}
}
}
};
public static Dictionary< Type,List< string>> IgnoreList(string key)
{
return ToIgnore [key];
}
}

每个控制器内部都会更改JSON Formatter,如下所示:

  GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new 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之后循环错误,当使用显式包含时为false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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