StackOverflowException Prevention while Serializing Entity Framework Object Graph in Json

I want to serialize the Entity Framework Self-Tracking Entities full graphic object (parent + child from one to many relationships) in Json.

For serialization, I use ServiceStack.JsonSerializer .

This is what my database looks like (for simplicity, I reset all the unnecessary fields):

ERD

I get a full profile graph as follows:

public Profile GetUserProfile(Guid userID) { using (var db = new AcmeEntities()) { return db.Profiles.Include("ProfileImages").Single(p => p.UserId == userId); } } 

The problem is that trying to serialize it:

 Profile profile = GetUserProfile(userId); ServiceStack.JsonSerializer.SerializeToString(profile); 

throws a StackOverflowException . I believe this is because EF provides an infinite model that rolls the serializer up. That is, I can technically call it: profile.ProfileImages[0].Profile.ProfileImages[0].Profile ... etc.

How can I “smooth out” my EF object graph or otherwise prevent ServiceStack.JsonSerializer from starting out of the situation?

Note. I don’t want to project my object onto an anonymous type (for example), because this will result in a very long and hard to maintain piece of code).

+4
servicestack jsonserializer entity-framework-4 self-tracking-entities
Feb 05 2018-12-12T00:
source share
3 answers

You have conflicting problems, the EF model is optimized for storing your data model in an RDBMS, and not for serialization - this is the role of a separate DTO. Otherwise, your customers will be tied to your database, where every change to your data model can break your existing customer service.

With that said, it would be right to keep the individual DTOs you type to determine the desired shape (aka wireformat) that you want the models to look from the outside world.

ServiceStack.Common includes built-in mapping functions (i.e. TranslateTo / PopulateFrom) that make it easy to map objects to the DTO and vice versa. Here is an example showing this:

https://groups.google.com/d/msg/servicestack/BF-egdVm3M8/0DXLIeDoVJEJ

An alternative is to decorate the fields that you want to serialize in your data model, with the fields [DataContract] / [DataMember]. Any properties not related to [DataMember] will not be serialized - so you should use this to hide circular references that raise a StackOverflowException.

+9
Feb 05 '12 at 17:50
source share

For my StackOverflowers colleagues who come up with this question, I will explain what I ended up doing:

In the described case, you need to use the standard .NET serializer (and not ServiceStack): System.Web.Script.Serialization.JavaScriptSerializer . The reason is that you can decorate navigation properties that you do not want the serializer to handle the [ScriptIgnore] attribute.

By the way, you can use ServiceStack.JsonSerializer for deserialization - it's faster than .NET, and you have no problems with the StackOverflowException that I asked about this.

Another problem is how to get Self-Tracking Entities to decorate the corresponding navigation properties with [ScriptIgnore] .

Explanation: Without [ScriptIgnore] , serialization (using the .NET Javascript serializer) will also throw an exception (similar to the problem that causes a StackOverflowException in ServiceStack). We need to eliminate roundness, and this is done using [ScriptIgnore] .

So, I edited the .TT file that came with the ADO.NET Self-Tracking Entity Generator Template and found that it contains [ScriptIgnore] in the appropriate places (if someone needs diff code, write me a comment). Some say it’s bad practice to edit these “external” non-editable files, but damn it solves the problem and this is the only way that does not force me to redesign my entire application (use POCOs instead of STE, use DTO for total, etc.)

@mythz: I do not quite agree with your debate about using DTO - see comments for your answer. I really appreciate your enormous efforts to create a ServiceStack (all modules!) And free use and open source. I just recommend that you either respect the [ScriptIgnore] attribute in your text serializers, or come up with your own attribute. Also, even if you can actually use DTOs, they cannot add navigation properties from the child back to the parent, as they will get a StackOverflowException. I mark your answer as "accepted" because in the end it helped me find my way in this matter.

+7
Feb 08 '12 at 20:38
source share

Be sure to separate the object from the ObjectContext before serializing it.

I also used Newton JsonSerializer.

JsonConvert.SerializeObject (EntityObject, Formatting.Indented, new JsonSerializerSettings {PreserveReferencesHandling = PreserveReferencesHandling.Objects});

+1
Feb 22 2018-12-22T00:
source share



All Articles