EF 4.1 - Code First - JSON Serial Link Error

I get a circular link error message, although as far as I know, I don't have any circular links. I take a set of orders from the database and send them to the client as JSON. All code is shown below.

This is mistake:

Mistake

A circular reference was found while serializing an object of type 'System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it occurred in the code.

Exception Details: System.InvalidOperationException: A circular reference was detected during serialization of an object of type 'System.Data.Entity.DynamicProxies.Order_83CECF2AA4DE38232F9077D4B26941AB96BC61230419EA8AC42C9100E6072812'.

Source Error:

An unhandled exception was thrown during the execution of the current web request. Information about the origin and location of the exception can be identified using the exception trace stack below.

My classes are as follows:

Order

public class Order { [Key] public int OrderId { get; set; } public int PatientId { get; set; } public virtual Patient Patient { get; set; } public int CertificationPeriodId { get; set; } public virtual CertificationPeriod CertificationPeriod { get; set; } public int AgencyId { get; set; } public virtual Agency Agency { get; set; } public int PrimaryDiagnosisId { get; set; } public virtual Diagnosis PrimaryDiagnosis { get; set; } public int ApprovalStatusId { get; set; } public virtual OrderApprovalStatus ApprovalStatus { get; set; } public int ApproverId { get; set; } public virtual User Approver { get; set; } public int SubmitterId { get; set; } public virtual User Submitter { get; set; } public DateTime ApprovalDate { get; set; } public DateTime SubmittedDate { get; set; } public Boolean IsDeprecated { get; set; } } 

A patient

 public class Patient { [Key] public int PatientId { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string MiddleInitial { get; set; } public bool IsMale; public DateTime DateOfBirth { get; set; } public int PatientAddressId { get; set; } public Address PatientAddress { get; set; } public bool IsDeprecated { get; set; } } 

Certification period

 public class CertificationPeriod { [Key] public int CertificationPeriodId { get; set; } public DateTime startDate { get; set; } public DateTime endDate { get; set; } public bool isDeprecated { get; set; } } 

Agency

 public class Agency { [Key] public int AgencyId { get; set; } public string Name { get; set; } public int PatientAddressId { get; set; } public virtual Address Address { get; set; } } 

Diagnostics

 public class Diagnosis { [Key] public int DiagnosisId { get; set; } public string Icd9Code { get; set; } public string Description { get; set; } public DateTime DateOfDiagnosis { get; set; } public string Onset { get; set; } public string Details { get; set; } } 

OrderApprovalStatus

 public class OrderApprovalStatus { [Key] public int OrderApprovalStatusId { get; set; } public string Status { get; set; } } 

User

 public class User { [Key] public int UserId { get; set; } public string Login { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string NPI { get; set; } public string Email { get; set; } } 

NOTE: ADDRESS CLASS - NEW ADDITION DURING EDITING

Address

 public class Address { [Key] public int AddressId { get; set; } public string StreetAddress { get; set; } public string City { get; set; } public string State { get; set; } public string Zip { get; set; } public string Phone { get; set; } public string Title { get; set; } public string Label { get; set; } } 

The code that performs the serialization is here:

Excerpt from OrderController

  public ActionResult GetAll() { return Json(ppEFContext.Orders, JsonRequestBehavior.AllowGet); } 

thank

+45
json c # serialization asp.net-mvc-3 entity-framework
Apr 07 2018-11-11T00:
source share
11 answers

You can try to remove the virtual from all navigation properties to disable lazy loading and proxy creation, and then use loading loading instead to explicitly load the desired graph of the object:

 public ActionResult GetAll() { return Json(ppEFContext.Orders .Include(o => o.Patient) .Include(o => o.Patient.PatientAddress) .Include(o => o.CertificationPeriod) .Include(o => o.Agency) .Include(o => o.Agency.Address) .Include(o => o.PrimaryDiagnosis) .Include(o => o.ApprovalStatus) .Include(o => o.Approver) .Include(o => o.Submitter), JsonRequestBehavior.AllowGet); } 

Referring to your previous post , it looks like your application does not rely on lazy loading, since you presented there virtual properties for loading a graphic object lazily, possibly causing serialization problems.

Edit

No need to remove the virtual from the navigation properties (which would make lazy loading completely impossible for the model). This is enough to disable the creation of a proxy server (which also disables lazy loading) for specific situations where proxy servers are worried, for example, serialization:

 ppEFContext.Configuration.ProxyCreationEnabled = false; 

This disables proxy creation only for a specific instance of ppEFContext .

(I just saw @WillC already mentioned this here. Upvote for this, please edit his answer.)

+47
Apr 7 '11 at 23:15
source share

When you know that you need to serialize from a specific context, you can disable proxy creation for this particular request, as shown below. This worked for me and was better than revising my models.

 using (var context = new MeContext()) { context.Configuration.ProxyCreationEnabled = false; return context.cars.Where(w => w.Brand == "Ferrari") } 

This approach takes the type of proxy object for this particular instance of the context, so the returned objects are the actual class, so serialization is not a problem.

t

 {Models.car} 

instead

 {System.Data.Entity.DynamicProxies.car_231710A36F27E54BC6CE99BB50E0FE3B6BD4462ECβ€Œβ€‹A19695CD1BABB79605296EB} 
+39
Mar 06
source share

The problem is that you are actually serializing the proxy object object created by the entity. Unfortunately, this is due to some problems when used with the JSON serializer. You might consider associating your objects with special classes of the POCO class for compatibility with JSON.

+9
Apr 07 2018-11-21T00:
source share

There is an attribute to add Entity Framework objects.

 [ScriptIgnore] 

This makes the code not execute Circular references.

+8
Oct 09 '11 at 19:36
source share

I think they fixed it in the latest version.

Check out the reference documents in the section β€œ Serializing and Deserializing JSON β†’ Serializing and Saving Object Links .”

Set this parameter when initializing the JSON.Net serializer:

 PreserveReferencesHandling = PreserveReferencesHandling.Objects; 

So an example would be like this:

 var serializerSettings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects }; string json = JsonConvert.SerializeObject(people, Formatting.Indented, serializerSettings); 

I checked that this works with my first code solution and the circular link in the navigation properties. If you look at the resulting JSON, it should have the properties "$ id" and "$ ref".

+7
Apr 10 2018-12-12T00:
source share

An alternative solution would be to use anonymous types as a result of the LINQ query.

In my project, I actively use lazy loading, and disabling it was wrong.

+6
Mar 18 2018-12-18T00:
source share

An alternative solution, if you need only some values ​​from the objects, is to create an anonymous class and return it, as shown below:

 public JsonResult AjaxFindByName(string term) { var customers = context.Customers .Where(c => c.Name.ToUpper().Contains(term.ToUpper())).Take(10) .AsEnumerable() .Select(c => new { value = c.Name, SSN = String.Format(@"{0:000\-00\-0000}", c.SSN), CustomerID = c.CustomerID }); return Json(customers, JsonRequestBehavior.AllowGet); } 
+3
Sep 02 '13 at 3:34
source share

A circular link occurs because you are using active object loading.

You have several methods:

  • Disable loading when loading a request (linq or lambda) DbContext.Configuration.ProxyCreationEnabled = false;
  • Remove the virtual keyword from Domainmodel
  • Detach objects (= no downloadable features and proxies)
    • Repository.Detach (EntityObject)
    • DbContext.Entry (entityObject) .EntityState = EntityState.Detached
  • Clone Properties
    • You can use something like AutoMapper to clone an object, do not use the ICloneable interface, because it also clones ProxyProperties in the object, so this will not work.
  • If you are creating an API, try using the separte project with a different configuration (which does not return a proxy)

PS. Proxies is an object created by EF when it is loaded from the Entity Framework. In short: this means that it contains the original values ​​and updated values ​​so that they can be updated later. It handles other things :-)

+2
Mar 04 '14 at 11:36
source share

For those using the EF / Linq2SQL proxy classes, my solution was to simply remove the parent link for my child objects.

So, in my model, I selected the connection and changed the "Parent" link to "Internal" rather than "Public".

It may not be the perfect solution for everyone, but it worked for me.

0
Feb 23 2018-12-12T00:
source share

You can remove the virtual :

public virtual Patient Patient { get; set; } public virtual Patient Patient { get; set; } β†’ public Patient Patient { get; set; } public Patient Patient { get; set; }

Keep in mind that when you delete the virtual keyword, lazy loading will be disabled.

0
Aug 18 2018-12-12T00:
source share
0
May 22 '13 at 17:23
source share



All Articles