实体框架DBSet包含没有代理

时间:2016-03-16 16:29:13

标签: c# json entity-framework

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

我正在测试一些表,它们是Project和Person。项目管理项目的人员参考人员,以及人员管理的所有项目从人员到项目的参考。为了让原来的回归工作,我添加了

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 });

代码执行正常,但随后我拨打电话我收到以下错误:

  

"消息":"发生错误。"," ExceptionMessage":"使用类型' DDBAPI检测到自引用循环.EntityFramework.Project&#39 ;.路径' [8] .Person.Projects'。"

是否有Include来阻止它加载循环引用?我看到类似的问题引用了制作DTO以限制被引入返回的内容,但由于通常我不知道我将要求哪个表格,我不知道我需要哪个DTO,因为我试图避免任何逻辑基于传入的表名称。

1 个答案:

答案 0 :(得分:1)

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

只需创建代理来处理更改跟踪,但它们具有与原始实体相同的属性。

您的问题是表PersonProject有一个导航属性,反之亦然。这是循环引用,如果您删除了其中一个表中的导航属性,即Person实体中的Project属性或Projects,则只能将其拆分。 Person实体中的财产。

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

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

然后您需要选择以下两个选项之一:

  • ReferenceLoopHandling = ReferenceLoopHandling.IgnoreDocs here
  • PreserveReferencesHandling = PreserveReferencesHandling.Objects Docs here

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