2012-03-27 10 views
9

私はASP.NET Web APIを使って素敵なAPIを構築しましたが、私のコンテキスト(エンティティフレームワーク)AsQueryableからエンティティを返すのは適切ではないと思いますので、すべてをDTOオブジェクトにマッピングしています。ASP.NET Web APIはクエリ可能なDTOを返しますか?

しかし、わかりませんが、私は自分のコンテキストをクエリ可能に保つことができますが、エンティティの代わりにDTOだけを返すことはできますか?またはこれは不可能ですか?

これは私のコードです:

public IQueryable<ItemDto> Get() 
{ 
    using (EfContext context = new EfContext()) 
    { 
     Mapper.CreateMap<Item, ItemDto>() 
      .ForMember(itemDto => itemDto.Category, mce => mce.MapFrom(item => item.Category.Name)); 

     IEnumerable<ItemDto> data = Mapper.Map<IEnumerable<Item>, IEnumerable<ItemDto>>(context.Items 
      .OrderByDescending(x => x.PubDate) 
      .Take(20)); 

     return data.AsQueryable(); 
    } 
} 

あなたは、私がデータをロード見て、その少しのIEnumerableコレクション照会可能を作ることができたよう。問題は、このコードに対して生成されたクエリは、最初にすべてのアイテム(または少なくとも20個の最初のアイテム)をロードしてから出力をフィルタするため、おそらく非常に非効率的なことです。

私は私の問題をできるだけ良く説明してほしいと思いますが、説明するのは少し難しいです。私はGoogle上でそれについて何も見つけることができませんでした。

+0

Web APIエンドポイントをIQueryableとして公開しないでください。本当に必要な場合は、Web API ODataを参照してください。それ以外の場合は、単純な古いRESTエンドポイントに固執し、コントローラアクションのパラメータとしてあらゆる種類のフィルタリングを可能にします。 – mare

答えて

7

メモリ内のすべてを最初に選択しないでください。

public IQueryable<ItemDto> Get() 
{ 
    using (EfContext context = new EfContext()) 
    { 
     var query = from item in context.Items 
        select Mapper.Map<Item, ItemDto>(item) 

     return query.OrderByDescending(x => x.PubDate).Take(20)); 
    } 
} 

ところで、次のコードを使用して、静的コンストラクタまたはWebApiConfig.csファイル、例えば、一度やってみたいものです。このような何かを行います。

Mapper.CreateMap<Item, ItemDto>() 
    .ForMember(itemDto => itemDto.Category, mce => mce.MapFrom(item => item.Category.Name)); 
+0

これはEF4で機能しますか?私が思い出したように、EFでは、EFで定義されていない型にマップすることはできませんでした。 –

+0

アプリケーションの起動時にマッピングを定義するだけで済むのですか?それを知らなかった。それを指摘してくれてありがとう:) –

+0

@ライアン。 EFクエリでは、EFエンティティを取得していますが、ロードされたものだけがAutoMapperを使用してDTOに変換されます。しかし、この方法では、遅延/遅延が発生し、データベース内で順序/フィルタリングが行われ、EFエンティティからDTOにマッピングされるのは最大20のレコードだけになります。 – Maurice

3

唯一のクエリは、表示されているコード(注文とテイク)で行われた場合、コードは問題ありません。結果のみをマップします(最大20)。しかし、IQueryableを返すので、結果をさらに照会したいと思います。 ODataスタイルのパラメータがありますか?

最大20個の項目を使用すると、コードを記述しない方がよいでしょう。残りのクエリはオブジェクトクエリとして実行されます。ただし、その制約(最大20)を削除するか、それ以降のクエリが行われた後にその制約を設定すると、この方法は非効率的になります。

基本的に、すべてのクエリをEFデータベースで実行する場合は、クエリチェーンの最後にマッピングを移動する必要があります。あなたは何ができるか

は実際に実際のエンティティが

public IQueryable<ItemDto> Get() 
    { 
     using (EfContext context = new EfContext()) 
     { 
      return context.items 
         .OrderByDescending(x => x.PubDate) 
         .Take(20)); 
     } 
    } 

オブジェクト戻り、MediaTypeFormatterでこれをシリアライズする方法MVCを伝えています。ここではAutoMapperを使用できます。 。

関連する問題