简体   繁体   中英

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. 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.

I have a couple tables that I am testing with, they are Project and 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.

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. 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'."

Is there anyway with Include to stop it from loading the circular reference? 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.

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. 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.

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. I do also suppose you're using Web API. If that's the case, you can find the JSON.NET serializer settings like this:

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

Then you need to choose one of these two options:

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

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. Docs here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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