13

EF4 CTP5を介して返されたオブジェクトをシリアル化しようとすると、循環参照に問題が発生します。私のモデルには、コードファーストアプローチと単純なpocoを使用しています。

オブジェクトへの逆参照を提供するプロパティに[ScriptIgnore]属性を追加しましたが、pocoを手動でインスタンス化すると、厄介なことにすべてが正常に機能するようです。つまり、JSONに正常にシリアル化され、scriptignore属性が確認されます。ただし、DALから返されたオブジェクトをシリアル化しようとすると、循環参照例外が発生します。「タイプ'System.Data.Entity.DynamicProxies.xxxx'のオブジェクトのシリアル化中に循環参照が検出されました。」

私はデータを取得するいくつかの方法を試しましたが、それらはすべてこのエラーで立ち往生しています:

    public JsonResult GetTimeSlot(int id) {
        TimeSlotDao tsDao = new TimeSlotDao();
        TimeSlot ts = tsDao.GetById(id);
        return Json(ts);
    }

以下の方法は、タイムスロットの動的プロキシオブジェクトが予定オブジェクトの循環参照を引き起こすのではなく、わずかにうまく機能します。

    public JsonResult GetTimeSlot(int id) {
        TimeSlotDao tsDao = new TimeSlotDao();
            var ts = from t in tsDao.GetQueryable()
                 where t.Id == id
                 select new {t.Id, t.StartTime, t.Available, t.Appointment};
        return Json(ts);
    }

この問題に対するアイデアや解決策はありますか?

更新 可能であれば、すぐに使用できるシリアライザーを使用したいと思いますが、代わりにnuget経由のJson.Netでも問題ありませんが、意図したとおりに使用できることを願っています...

4

5 に答える 5

4

IISでホストされているWCFサービスで同様の問題が発生し、DataContractJsonSerializerクラスを使用してPOCOオブジェクトをシリアル化しようとしました。組み込みのJSONシリアライザーは、循環参照をまったく処理していないようです。JSON.netシリアライザーを使用して自分でシリアル化を処理し、メソッドからjson文字列を返すだけで、この問題を回避することができました。JSON.netシリアライザーには、json自体が循環参照をサポートしていないため、循環参照を無視するオプションがあります。

于 2011-01-05T20:22:36.327 に答える
2

動的プロキシを何をしたとしても、問題が発生し続けましたが、モデル内のすべての循環参照を削除するところまで行きました。しかし、それでも問題は解決しませんでした。

Json.Netを試しましたが、同じ問題が発生しました。

結局、カスタムJavaScriptConverterの使用に関する投稿に出くわしました

http://hellowebapps.com/2010-09-26/produce-json-from-entity-framework-4-0-generated-classes/

コードを実装し、すべてが機能した叔父をボブします

于 2011-01-06T12:50:47.830 に答える
1

外部のJSONシリアライザーに頼ることなくこれを解決しました。一言で言えば、オブジェクトコンテキストのコンストラクターでProxyCreationを無効にしました。

なぜこれが機能するのかわかりませんが、ここにフォローアップの質問を投稿しました。

于 2011-01-21T00:57:36.237 に答える
1

次のContractResolverを使用しました。CamelCaseContractPropertyResolverから継承してその機能を取得しましたが、DefaultContractResolverから直接継承することもできます。

using System;
using System.Collections.Generic;
using System.Reflection;
using Newtonsoft.Json.Serialization;

namespace MyNamespace
{
    /// <summary>
    /// This class enables EntityFramework POCO objects to be serialized. In some cases POCO
    /// objects are subclassed by a proxy which has an additional member _entityWrapper. This
    /// object prevents serialization (circular references and references to non-serializable types).
    /// This removes the _entityWrapper from the list of members to be serialized.
    /// </summary>
    public class ContractResolver : CamelCasePropertyNamesContractResolver
    {
        protected override List<MemberInfo> GetSerializableMembers(Type objectType)
        {
            if (objectType.FullName.StartsWith("System.Data.Entity.DynamicProxies."))
            {
                var members = base.GetSerializableMembers(objectType);
                members.RemoveAll(memberInfo => memberInfo.Name == "_entityWrapper");
                return members;
            }
            return base.GetSerializableMembers(objectType);
        }
    }
}

これを使用するには、シリアライザーを作成してから、ContractResolverプロパティをこのクラスの新しいインスタンスに設定します。

var ser = JsonSerializer.Create(sJsonSerializerSettings);            
ser.ContractResolver = new ContractResolver(); 
于 2011-11-15T15:06:19.617 に答える
0

私もこの問題に遭遇しました。このトピックへの回答には、いくつかの解決策が含まれています。しかし、説明があり、さらにカスタムシリアル化がない場合のさまざまなケースに最適なさまざまなソリューションは、HongyeSunの記事-WebAPIで のループ参照処理で見つかりました。

于 2013-04-16T11:35:38.943 に答える