获取JSON序列化实体框架自引用循环错误,即使在使用显式包含时ProxyCreation为false之后也是如此

Aka*_*hia 5 entity-framework lazy-loading json.net asp.net-mvc-4 asp.net-web-api

JSON序列化(ASP.Net Web API)由于自引用循环而失败(这是一个常见问题,原因:被请求的实体延迟加载子实体,并且每个子实体都有父实体的后引用).

我找到了解决办法,但对我没有帮助:

  1. 使用[JsonIgnore]忽略导航属性: 此解决方案有效,但不适用于我的情况.例如:要获取客户信息及其订单,我会在Order类中快速添加[JsonIgnore]到Customer属性,但是当我想获得订单信息以及客户详细信息时,因为客户属性上有[JsonIgnore] ,它不包括客户详细信息.
  2. 更改JSON.Net Serializer设置以保留引用:无法保留,因为我不需要循环引用数据.
  3. 在数据上下文中禁用代理创建并使用显式加载(这应该理想地解决问题):禁用代理创建会停止Lazy Loading并返回数据而不会出现错误,但是当我明确包含子实体时,我再次得到意外的自引用循环错误!该错误位于父实体的后引用级别.

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

Aka*_*hia 3

我尝试了所有建议的解决方案,但没有成功。最终将 JSON.Net Serializer\xe2\x80\x99s DefaultContractResolver 重写为:

\n\n
public class FilterContractResolver : DefaultContractResolver\n{\n    Dictionary<Type, List<string>> _propertiesToIgnore;\n\n    public FilterContractResolver(Dictionary<Type, List<string>> propertiesToIgnore)\n    {\n        _propertiesToIgnore = propertiesToIgnore;\n    }\n\n    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)\n    {\n        var property = base.CreateProperty(member, memberSerialization);\n        List<string> toIgnore;\n        property.Ignored |= ((_propertiesToIgnore.TryGetValue(member.DeclaringType, out toIgnore) || _propertiesToIgnore.TryGetValue(member.DeclaringType.BaseType, out toIgnore)) && toIgnore.Contains(property.PropertyName));\n        return property;\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

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

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

\n\n
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new FilterContractResolver(CriteriaDefination.IgnoreList("tblCustomer"));\n
Run Code Online (Sandbox Code Playgroud)\n