简体   繁体   中英

How to serialize entity if using lazy loading in entity framework?

I just started to learn entity framework and i am facing the problem related to serialization of generated Models. I have tables with one to many relation which are Country and State as one country have many states. I am using the DB first approach and when i create the entities using Entity Framework, the class Country has one property of ICollection. I read and found that this is the navigation property. Let me show the generated class first which is below:

//This is the generated class.

 public class Country
    {
        public Country()
        {
                States = new HashSet<States>();
        }
        public int Id { get; set; }
        public string ContryCode  { get; set; } 
        public string ContryName  { get; set; }    
        public virtual ICollection<States> States{ get; set; }

    }

I generated Models and then i step forwarded. Then i got the problem of serialization when i request via ajax to get the list for Country. I googled and found some terms like lazy loading, eager loading and n+1 problem. I read about it in detail. I found a solution which was turning off the lazy loading. Now the question is How i can serialize my Model with lazy loading?

I have created MetaData class and use some attribute like ignoreXml etc but nothing helped. By the way i am using Asp.Net MVC 5 and i want to serialize my Model with lazy loading. Can any one explain?

When you use lazy loading, execution is deferred until the value of the property is actually needed. You are probably encountering an error because the context has been disposed by the time the property is accessed. Consider the following scenario:

  • You have an object called Country with a lazy-loaded property called States .
  • You get this object from a context.
  • The context is disposed.
  • You call the States property.
  • The property goes looking for the context it came from.
  • An error is thrown because "the context has been disposed".

Code Sample:

using(var context = new SomeEntityContext())
{
     var country = context.Countries.First();
}

//This will throw an error because the context was disposed of.
var states = country.States; 

The serializer would also throw an error because it will go through the properties of the object, it will find States and it will try to get its value.

Even if the context is still alive, you could run into a loop with navigational properties during serialization. this is because both objects hold a reference to each other. Consider the following scenario:

  • You have an object called Country with a lazy-loaded property called States .
  • The serializer attempts to serializer the object of type Country .
  • It reads the States collection.
  • It attempts to serialize every object of type State .
  • It reads a property of type Country .
  • It attempts to serialize the object of type Country .
  • It reads the States collection.
  • It attempts to serialize every object of type State .
  • It reads a property of type Country .
  • It reads the States collection.
  • It attempts to serialize every object of type State .
  • It reads a property of type Country .
  • It reads the States collection.
  • It attempts to serialize every object of type State .
  • It reads a property of type Country .
  • .... (endless loop, well, at least until you run out of stack frames).

Alternatively, you can create a custom serializer that will avoid the pitfalls of navigational properties, but that is probably more work than it's worth. This approach is best suited for situations where the serialized version differs significantly from the object.

This is why you are better off using a Data Transfer Object (DTO). Map the data to this object and send that over the wire. There are components out there that can do the mapping for you, if you keep the structures as similar as possible.

Check out AutoMapper: http://automapper.org/

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