1

Entity Framework Code First で使用するためにセットアップされた POCO オブジェクトがいくつかあります。

ASP.NET MVC 4 Web サイトの ApiController からこれらのオブジェクトの 1 つを返し、それをクライアント アプリケーションで使用したいと考えています。

Entity Framework が邪魔をしていたため ( Can an ApiController return an object with a collection of other objects? を参照してください)、EF プロキシをシリアル化しようとしていたためです。プレーンな POCO オブジェクトではなく、オブジェクト。そのため、これを回避するために DbContext でプロキシ生成をオフにしました。これで、シリアル化されたオブジェクトは (私の目には) 問題ないように見えます。

問題のオブジェクトは「タグ」です。これが私の POCO クラスです。

public class Tag
{
    public int Id { get; set; }

    public int ClientId { get; set; }
    public virtual Client Client { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public bool IsActive { get; set; }
}

かなり標準的なものですが、ClientId と Client メンバーに注意してください。これらは EF Code First の「ナビゲーション」プロパティです。(すべてのタグは正確に 1 つのクライアントに属します)。

ApiController から取得したものは次のとおりです。

<Tag xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Foo">
  <Client i:nil="true"/>
  <ClientId>1</ClientId>
  <Id>1</Id>
  <IsActive>true</IsActive>
  <Name>Example</Name>
</Tag>

プロキシ生成を無効にすると、参照されたオブジェクトの自動読み込みが得られないため、Client メンバーは nil です。この場合は問題ありません。クライアント側でそのデータは必要ありません。

そのため、クライアント側でこれらのオブジェクトを逆シリアル化しようとしています。新しいクラスを作成するのではなく、クライアント アプリケーションで同じ POCO クラスを再利用できることを望んでいました。DRYとそのすべて。だから、私はしようとしています:

XmlSerializer xmlSerializer = new XmlSerializer(typeof(Tag));

var tag = xmlSerializer.Deserialize(stream);

しかし、私は 2 つの問題に遭遇しました。どちらも EF Code First の規則によるものです。

問題 1 : 私の Tag クラスには Client メンバーがあるため、XmlSerializer はそれを逆シリアル化する方法がわからないという不平を言っています。これで十分だと思います (メンバーが XML で Nil だったので気にしないことを期待していましたが)。XmlSerializer コンストラクターで追加の型を渡すことができました。それを試みたところ、クライアントが使用する他のクラスについて不平を言いました。Client はあらゆる種類の他のオブジェクトを参照するため、それらすべてを渡す必要があります。

[DataContract] および [DataMember] 属性を使用して、クライアント メンバーを XML から削除しようとしました (DataMember としてマークしないことにより)。これにより XML から削除されましたが、XmlSerializer がそれについて泣き言を言うのを止めることはできませんでした。したがって、問題は XML にあるという事実ではなく、クラス定義にあると思います。

問題 2 : typeof(Client) を追加の型として渡そうとしたところ、インターフェイス メンバーが含まれているため、そのクラスを逆シリアル化できないと不平を言いました。これは、再び EF Code First の規則により、次のような Tags メンバーがあるためです。

`public virtual ICollection<Tag> Tags { get; set; }`

そのため、参照型の問題を解決したとしても、POCO クラスを使用することはまだできないようです。

これに対する解決策はありますか、それともクライアント側で純粋に使用するために新しい DTO クラスを作成し、それらを ApiController から返す必要がありますか?

4

1 に答える 1

0

DataContractSerializerの代わりに を使用してみましたがXmlSerializer、動作しているように見える Tag クラスに使用しました。ICollection<T>仮想メンバーを持つクラスではまだ試していません...

更新:試してみたところ、「動作」しました。それでもオブジェクトを再構築し、ICollectionメンバーを null のままにします。

更新 2: OK、それは行き止まりであることが判明しました。はい、それはクラスを正しくシリアル化および逆シリアル化できることを意味していましたが、誰もが私に言い続けていたように、DTO クラスの方が良い方法でした。(DTO = データ転送オブジェクト - 回線を介してデータを転送するために特別に作成されたクラスで、おそらく元のフィールドのサブセットを使用します)。

私は現在 AutoMapper を使用しています (Cuong Le に感謝します)。これにより、POCO エンティティをシリアル化のためのより単純な DTO クラスに簡単に変換できます。これは、同じ問題に直面しているすべての人にお勧めします。

于 2012-08-01T13:54:48.580 に答える