4

Entity Framework Self-Tracking Entitiesの完全なオブジェクト グラフ (1 対多の関係にある親 + 子) を Json にシリアル化したいと考えています。

シリアル化には、ServiceStack.JsonSerializerを使用します。

これは私のデータベースがどのように見えるかです (簡単にするために、無関係なフィールドをすべて削除しました):

ERD

この方法で完全なプロファイル グラフを取得します。

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

問題は、それをシリアル化しようとすることです:

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

を生成しStackOverflowExceptionます。これは、シリアライザーを台無しにする無限モデルを EF が提供しているためだと思います。つまり、技術的には : などを呼び出すことができますprofile.ProfileImages[0].Profile.ProfileImages[0].Profile ...

EF オブジェクト グラフを「平坦化」したり、ServiceStack.JsonSerializerがスタック オーバーフロー状態にならないようにするにはどうすればよいですか?

注:オブジェクトを匿名型に投影したくありません(これらの 提案のように)、非常に長くて保守が難しいコードの断片が導入されるためです)。

4

3 に答える 3

9

相反する懸念があります.EFモデルは、データモデルをRDBMSに格納するために最適化されており、シリアル化には最適化されていません-これは、個別のDTOを持つ役割です。そうしないと、クライアントがデータベースにバインドされ、データ モデルを変更するたびに既存のサービス クライアントが壊れる可能性があります。

そうは言っても、モデルが外の世界からどのように見えるかを示す目的の形状 (別名ワイヤ形式) を定義するマッピング先の個別の DTO を維持するのが正しいことです。

ServiceStack.Commonには組み込みのマッピング関数 (つまり、TranslateTo/PopulateFrom) が含まれており、エンティティと DTO の間のマッピングを簡素化します。これを示す例を次に示します。

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

別の方法は、データ モデルでシリアル化するフィールドを [DataContract] / [DataMember] フィールドで装飾することです。[DataMember] に関連付けられていないプロパティはシリアル化されません。したがって、これを使用して、StackOverflowException の原因となっている循環参照を非表示にします。

于 2012-02-05T17:50:55.947 に答える
7

この質問に答える私の仲間の StackOverflowers のために、私が最終的に何をしたかを説明します。

私が説明したケースでは、(ServiceStack ではなく) 標準の .NET シリアライザーを使用する必要がありますSystem.Web.Script.Serialization.JavaScriptSerializer。その理由は、シリアライザーに処理させたくないナビゲーション プロパティを属性で装飾できるから[ScriptIgnore]です。

ちなみに、まだServiceStack.JsonSerializer逆シリアル化に使用できます-.NETよりも高速で、この質問で尋ねたStackOverflowExceptionの問題はありません。

もう 1 つの問題は、Self-Tracking Entities を取得して、関連するナビゲーション プロパティを で装飾する方法[ScriptIgnore]です。

説明:を使用しない[ScriptIgnore]場合、(.NET Javascript シリアライザーを使用して) シリアライズすると、循環参照に関する例外も発生します (ServiceStack で StackOverflowException が発生する問題と同様)。循環性を排除する必要があり、これは を使用して行われ[ScriptIgnore]ます。

そこで、 ADO.NET Self-Tracking Entity Generator Template.TTに付属のファイルを編集し、関連する場所に含めるように設定しました(コードの差分が必要な場合は、コメントを書いてください)。これらの「外部」の、編集する意図のないファイルを編集するのは悪い習慣だと言う人もいますが、一体、それは問題を解決し、全体を再構築することを強制しない唯一の方法ですアプリケーション (STE の代わりに POCO を使用する、すべてに DTO を使用するなど)[ScriptIgnore]

@mythz: DTO の使用に関するあなたの主張には絶対に同意しません。回答に対するコメントを参照してください。ServiceStack (すべてのモジュール!) を構築し、それを無料でオープンソースにできるようにしてくださった多大な努力に本当に感謝しています。テキストシリアライザーの [ScriptIgnore] 属性を尊重するか、独自の属性を考え出すことをお勧めします。そうしないと、実際にDTO を使用できる場合でも、StackOverflowException が発生するため、子オブジェクトから親オブジェクトにナビゲーション プロパティを追加することはできません。結局のところ、この問題で自分の道を見つけるのに役立ったので、あなたの答えを「承認済み」とマークします。

于 2012-02-08T20:38:22.083 に答える
1

シリアライズする前に、必ず ObjectContext からエンティティをデタッチしてください。

Newton JsonSerializer も使用しました。

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

于 2012-02-22T10:54:30.293 に答える