2

EF 5 と ASP.NET Web API を使用して、コントローラーから JSON を返しています。私の例はペットサービスです。この質問では、エンティティはClientPet、およびVeterinarianです。関係は次のとおりです。

クライアント => 一対多 => ペット => 一対一 => 獣医師

そして、階層を逆にします。

獣医師 => 一対多 => ペット => 一対一 => クライアント

私のPetsControllerでは、GetPetsアクションは次のようになります。

var pets= db.Pets
    .Where(p => p.IsActive == true)
    .Include(p => p.Client)
    .Include(p => p.Veterinarian);

return Mapper.Map<IEnumerable<Pet>, IEnumerable<PetDTO>>(pets); // Using Automapper to map to a DTO

結果の JSON には Pets があり、各 Pet には Client、各 Pet には Veterinarian 、および各 Veterinarian には Pets のコレクションがあります。

ペットのコレクションが JSON に表示される理由は理解できますが、(少なくとも今は) コントローラー アクションからのペットのリストとは関係ありません。ペットのコレクションを削除するエレガントな方法を探しています。現在、私はハックのように感じるものを使用しています:

var pets= db.Pets
    .Where(p => p.IsActive == true)
    .Include(p => p.Client)
    .Include(p => p.Veterinarian);

foreach (Pet pet in pets) {
    pet.Veterinarian.Pets = null; // Remove the Pets collection before serializing
}

return Mapper.Map<IEnumerable<Pet>, IEnumerable<PetDTO>>(pets); // Using Automapper to map 

IQuerableシリアライザーといくつかの方法 (その多くはよく知らない) でいくつかのことを試しましたが、役に立ちませんでした。

4

1 に答える 1

1

遅延読み込みを無効にして、グラフを整理できます。しかし、それでも常に問題が解決するとは限りません。双方向の関係 (pet <=> Veterinarian など) がある場合、Include を使用して関係の一方の側をフェッチすると、もう一方の側も自動的に構築されます。したがって、クエリpet.Veterinarian.Petsで明示的に要求していなくても、クエリは null になりませんInclude

DTO を使用することは、私が考えることができる最良の方法です。オブジェクト グラフを完全に制御できます。

また、OData プロトコルには、このメカニズムが $select と $expand によって既に定義されており、クライアントが必要とするオブジェクト グラフの深さと幅を指定するための制御が提供されます。たとえば、このシナリオでは、OData の URL は次のようになります~/Pets?$expand=Client,Veterinarian。ニーズに合わせて OData を検討しましたか?

毎回 DTO を作成したくない場合は、匿名オブジェクトを使用してオンザフライで作成できます。たとえば、シナリオでは、次のことができます。

db.Pets.Select(p => new 
{ 
    Id = p.ID, 

    .... other pet properties you want, 

    Veterinarian = new 
    { 
        ID = p.Veterinarian.ID 
        ... other veterinarian properties you want
    },
    Client = 
    {
        ... client properties you need.
    }

});

ただし、これはマッピングをselect句に移動しているだけです。

于 2013-03-28T16:49:11.597 に答える