【问题标题】:Entity Framework DBSet Include without proxies实体框架 DBSet 包含没有代理
【发布时间】:2016-03-16 16:29:12
【问题描述】:

我正在尝试创建一个方法,该方法使用 REST Web 服务的反射来访问我的实体框架(数据库优先)上下文。我已经获取了表格并将其转换为退货列表,但是当我尝试使用 Include 获取一些相关表格时遇到了麻烦。

我有几个要测试的表,它们是 Project 和 Person。 Project 对管理项目的人员有一个对 Person 的引用,对一个人管理的所有项目都有一个从 Person 到 Project 的引用。为了让原来的复工我加了

Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;

到我的上下文的类,以便删除引用循环并且 JSON 序列化正常工作。

我面临的问题是我现在试图明确获取所有项目以及与该项目相关的人员记录,而不包括该人员的项目列表。但是当我尝试包含人员时,我收到 JSON 序列化错误,因为它正在拉回循环引用。我目前有以下代码:

Entities context = new Entities();

// Normally these will be a parameters to the calling method
string tableName = "Projects";
string includeTableName = "Person";

System.Reflection.PropertyInfo propertyInfo = context.GetType().GetProperty(tableName);
Type type = propertyInfo.PropertyType;
dynamic list = propertyInfo.GetValue(context);

var include = typeof(QueryableExtensions).GetMethod("Include", new[] { typeof(IQueryable), typeof(string) });
var toList = typeof(Enumerable).GetMethod("ToList").MakeGenericMethod(type.GenericTypeArguments[0]);
list = include.Invoke(null, new object[] { list, includeTableName });
return toList.Invoke(null, new object[] { list });

代码正常执行,但随后我调用我得到以下错误:

"Message":"发生错误。","ExceptionMessage":"检测到类型为'DDBAPI.EntityFramework.Project'的自引用循环。路径'[8].Person.Projects'。"

Include 有没有办法阻止它加载循环引用?我看到了类似的问题,这些问题提到了制作 DTO 以限制返回的内容,但由于通常我不知道我将调用哪个表,所以我不知道我需要哪个 DTO,因为我试图避免任何基于周围的逻辑传入的表名。

【问题讨论】:

    标签: c# json entity-framework


    【解决方案1】:

    删除代理创建并不能解决循环引用问题。与此无关。

    代理只是为了处理更改跟踪而创建的,但它们具有原始实体的相同属性。

    您的问题是从表PersonProject 有一个导航属性,反之亦然。这就是循环引用,只有在删除其中一个表中的导航属性(即Project 实体中的Person 属性或Person 实体中的Projects 属性)时才能破坏它。

    您很可能不想这样做。因此,您需要做的是指示序列化程序,以便它可以处理循环引用。我想您使用的是 JSON.NET,默认情况下它是当前的 JSON 序列化程序。我还假设您正在使用 Web API。如果是这种情况,您可以像这样找到 JSON.NET 序列化程序设置:

    JsonSerializerSettings serializerSettings = GlobalConfiguration
      .Configuration.Formatters.JsonFormatter.SerializerSettings;
    

    那么你需要选择以下两个选项之一:

    • ReferenceLoopHandling = ReferenceLoopHandling.IgnoreDocs here
    • PreserveReferencesHandling = PreserveReferencesHandling.ObjectsDocs here.

    还有另一种解决方案:您可以通过使用[JsonIgnore] 属性装饰JSON.NET 来指示JSON.NET 不序列化它,而不是删除负责循环引用的导航属性。 Docs here.

    【讨论】:

    • 感谢您的帮助。我选择了ReferenceLoopHandling = ReferenceLoopHandling.Ignore,现在它的行为完全符合预期。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-10
    • 2013-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 2016-06-08
    相关资源
    最近更新 更多