简体   繁体   English

没有代理的实体框架DBSet包含

[英]Entity Framework DBSet Include without proxies

I am trying to create a method that accesses my Entity Framework (database first) context using reflection for a REST web service. 我正在尝试创建一种使用REST Web服务的反射访问我的实体框架(首先是数据库)上下文的方法。 I have gotten as far as getting the table, and converting it to a list for returns, but I am running into trouble when I try to use Include to get some of the related tables. 我已经获得了表格,并将其转换为返回列表,但是当我尝试使用Include来获取一些相关表格时,我遇到了麻烦。

I have a couple tables that I am testing with, they are Project and Person. 我有几个要测试的表,它们是Project和Person。 Project has a reference to Person for the person who manages the project and a reference back from Person to Project for all the projects a person manages. 对于项目的管理人员,项目具有对人员的引用,对于人员管理的所有项目,项目均具有从人员到项目的引用。 In order to get the original return to work I added 为了使工作恢复原状,我添加了

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

to my context's class so that the referential loop is removed and the JSON serialization works correctly. 到我的上下文的类中,以便删除引用循环,并且JSON序列化可以正常工作。

The problem I am facing is that I am now trying to explicitly get all the projects, and the person record related to the project, without including the list of the person's projects. 我面临的问题是我现在正在尝试显式获取所有项目以及与该项目相关的人员记录,而不包括该人员的项目列表。 But when I try to include people, I get the JSON serialization error because it is pulling back the circular reference. 但是当我尝试包含人员时,我收到JSON序列化错误,因为它拉回了循环引用。 I currently have the following code: 我目前有以下代码:

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

The code executes properly but then I make the call I get the following error: 该代码可以正确执行,但随后进行调用时出现以下错误:

"Message":"An error has occurred.","ExceptionMessage":"Self referencing loop detected with type 'DDBAPI.EntityFramework.Project'. Path '[8].Person.Projects'." “,”消息“:”发生错误。“,” ExceptionMessage“:”检测到类型为'DDBAPI.EntityFramework.Project'的自引用循环。路径为[[8] .Person.Projects'。

Is there anyway with Include to stop it from loading the circular reference? 无论如何,是否Include可以阻止它加载循环引用? I saw similar questions that referenced making DTOs to limit what gets pulled into the return but since normally I will not know what table I will be calling against, I will not know which DTO I would need as I am trying to avoid any logic based around the table names being passed in. 我看到了类似的问题,这些问题涉及使DTO限制返回收益,但是由于通常我不知道要针对哪个表,因此我将不知道需要哪个DTO,因为我试图避免基于任何逻辑传入的表名。

Removing the proxy creation doesn't solve the circular reference problem. 删除代理创建并不能解决循环引用问题。 It has nothing to do with it. 它与它无关。

The proxies are simply created to handle the change tracking, but they have the same properties of the original entities. 仅创建代理来处理更改跟踪,但是它们具有与原始实体相同的属性。

Your problem is that there is a navigation property from table Person to Project and viceversa. 您的问题是从表PersonProject都有一个导航属性,反之亦然。 That's the circular reference, and you could only break it if you removed the navigation property in one of the tables, ie the Person property in Project entity, or the Projects property in Person entity. 这是循环引用,并且只有在删除了其中一个表中的导航属性(即Project实体中的Person属性或Person实体中的Projects属性)时,才可以破坏它。

Most probably you don't want to do this. 您很可能不想这样做。 So, what you need to do is to instruct the serializer so that it can handle the circular references. 因此,您需要做的是指示序列化程序,使其可以处理循环引用。 I suppose you're using JSON.NET, which is the current JSON serializer by default. 我想您正在使用JSON.NET,它是默认情况下的当前JSON序列化程序。 I do also suppose you're using Web API. 我还假设您正在使用Web API。 If that's the case, you can find the JSON.NET serializer settings like this: 如果是这种情况,您可以找到像这样的JSON.NET序列化器设置:

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

Then you need to choose one of these two options: 然后,您需要选择以下两个选项之一:

  • ReferenceLoopHandling = ReferenceLoopHandling.Ignore . ReferenceLoopHandling = ReferenceLoopHandling.Ignore Docs here . 文档在这里
  • PreserveReferencesHandling = PreserveReferencesHandling.Objects Docs here . PreserveReferencesHandling = PreserveReferencesHandling.Objects 此处的文档

There is still another solution: instead of removing one of the navigation properties responsible for the circular reference, you can instruct JSON.NET to not serialize it by decorating it with [JsonIgnore] attribute. 还有另一种解决方案:您可以通过使用[JsonIgnore]属性修饰JSON.NET来指示不对它进行序列化,而不是删除负责循环引用的导航属性之一。 Docs here . 文档在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM