Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
334 views
in Technique[技术] by (71.8m points)

c# 4.0 - Preventing StackOverflowException while serializing Entity Framework object graph into Json

I want to serialize an Entity Framework Self-Tracking Entities full object graph (parent + children in one to many relationships) into Json.

For serializing I use ServiceStack.JsonSerializer.

This is how my database looks like (for simplicity, I dropped all irrelevant fields):

ERD

I fetch a full profile graph in this way:

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

The problem is that attempting to serialize it:

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

produces a StackOverflowException. I believe that this is because EF provides an infinite model that screws the serializer up. That is, I can techincally call: profile.ProfileImages[0].Profile.ProfileImages[0].Profile ... and so on.

How can I "flatten" my EF object graph or otherwise prevent ServiceStack.JsonSerializer from running into stack overflow situation?

Note: I don't want to project my object into an anonymous type (like these suggestions) because that would introduce a very long and hard-to-maintain fragment of code).

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You have conflicting concerns, the EF model is optimized for storing your data model in an RDBMS, and not for serialization - which is what role having separate DTOs would play. Otherwise your clients will be binded to your Database where every change on your data model has the potential to break your existing service clients.

With that said, the right thing to do would be to maintain separate DTOs that you map to which defines the desired shape (aka wireformat) that you want the models to look like from the outside world.

ServiceStack.Common includes built-in mapping functions (i.e. TranslateTo/PopulateFrom) that simplifies mapping entities to DTOs and vice-versa. Here's an example showing this:

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

The alternative is to decorate the fields you want to serialize on your Data Model with [DataContract] / [DataMember] fields. Any properties not attributed with [DataMember] wont be serialized - so you would use this to hide the cyclical references which are causing the StackOverflowException.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...