我正在尝试使用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,因为我试图避免任何逻辑基于传入的表名称。
答案 0 :(得分:1)
删除代理创建并不能解决循环引用问题。它与它无关。
只需创建代理来处理更改跟踪,但它们具有与原始实体相同的属性。
您的问题是表Person
到Project
有一个导航属性,反之亦然。这是循环引用,如果您删除了其中一个表中的导航属性,即Person
实体中的Project
属性或Projects
,则只能将其拆分。 Person
实体中的财产。
很可能你不想这样做。因此,您需要做的是指示序列化程序,以便它可以处理循环引用。我想您正在使用JSON.NET,默认情况下是当前的JSON序列化程序。我也假设您正在使用Web API。如果是这种情况,您可以找到JSON.NET序列化程序设置,如下所示:
JsonSerializerSettings serializerSettings = GlobalConfiguration
.Configuration.Formatters.JsonFormatter.SerializerSettings;
然后您需要选择以下两个选项之一:
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
。 Docs here。PreserveReferencesHandling = PreserveReferencesHandling.Objects
Docs here。还有另一种解决方案:您可以通过使用[JsonIgnore]
属性进行装饰来指示JSON.NET不对其进行序列化,而不是删除负责循环引用的导航属性之一。 Docs here