2013-05-16 8 views
8

WebApiにODataを実装しようとしています。私はリポジトリパターンとEF5(バックエンドで)を使用していますが、これは私が見つけたすべての例と一貫しています。ここで物事がうまくいくところです。私は、コントローラのAutoMapperを使用してマップされているモデルの背後にあるEF生成クラスを非表示にしようとしています。私が見た例は、レポから出てくるものを返すようです。WebApiとマップされたモデルでODataを実装する

コントローラーではなく、リポジトリ内の値を保持するためにODataパラメーターを適用したくありません。実行。私はリポジトリにODataCriteriaを渡すことができますが、Appyにしようとするとオプション/結果がIQueryable <モデル>プレゼンテーション層からIQueryable < EF_Class>に入力されたように見えるため、エラーが発生します。

私は誰かが別の投稿でこれを逃したのを見ましたが、投稿のマイナーな部分であり、役に立たなかったようです。

誰かがこれに対処しましたか?私は本当にEFクラスを公開したくありません。ああ、私はまずDBを使用しています。

事前のおかげで...

答えて

0

あなたの要件を示すコードは次のとおりです。

結果を得るには、クエリが実行されていることを確認する必要があります(ToList()を使用)。これを行う最も効率的な方法は、ページング(ボーナス)を追加してPageResult<>オブジェクトを返すことです。

public PageResult<WebPoco> Get(ODataQueryOptions<WebPoco> queryOptions) 
{ 
    var data2 = DatabaseData(); 

    //Create a set of ODataQueryOptions for the internal class 
    ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
    modelBuilder.EntitySet<DatabasePoco>("DatabasePoco"); 
    var context = new ODataQueryContext(
     modelBuilder.GetEdmModel(), typeof(DatabasePoco)); 
    var newOptions = new ODataQueryOptions<DatabasePoco>(context, Request); 

    var t = new ODataValidationSettings() { MaxTop = 25 }; 
    var s = new ODataQuerySettings() { PageSize = 25 }; 
    newOptions.Validate(t); 
    IEnumerable<DatabasePoco> results = 
     (IEnumerable<DatabasePoco>)newOptions.ApplyTo(data2, s); 

    int skip = newOptions.Skip == null ? 0 : newOptions.Skip.Value; 
    int take = newOptions.Top == null ? 25 : newOptions.Top.Value; 

    List<DatabasePoco> internalResults = results.Skip(skip).Take(take).ToList(); 

    // map from DatabasePoco to WebPoco here: 
    List<WebPoco> webResults; 

    PageResult<WebPoco> page = 
     new PageResult<WebPoco>(
      webResults, Request.GetNextPageLink(), Request.GetInlineCount()); 

    return page; 
} 

ここで使用してステートメント

using System.Web.Http; 
using System.Web.Http.OData; 
using System.Web.Http.OData.Builder; 
using System.Web.Http.OData.Query; 

テストクラス

public class WebPoco 
{ 
    public int id { get; set; } 
    public string name { get; set; } 
    public string type { get; set; } 
} 

public class DatabasePoco 
{ 
    public int id { get; set; } 
    public string name { get; set; } 
    public string type { get; set; } 
} 

とうーん、それを愛していない

private IQueryable<DatabasePoco> DatabaseData() 
{ 
    return (
     new DatabasePoco[] { 
      new DatabasePoco() { id = 1, name = "one", type = "a" }, 
      new DatabasePoco() { id = 2, name = "two", type = "b" }, 
      new DatabasePoco() { id = 3, name = "three", type = "c" }, 
      new DatabasePoco() { id = 4, name = "four", type = "d" }, 
      new DatabasePoco() { id = 5, name = "five", type = "e" }, 
      new DatabasePoco() { id = 6, name = "six", type = "f" }, 
      new DatabasePoco() { id = 7, name = "seven", type = "g" }, 
      new DatabasePoco() { id = 8, name = "eight", type = "h" }, 
      new DatabasePoco() { id = 9, name = "nine", type = "i" } 
     }) 
     .AsQueryable(); 
} 
+0

私はこのアプローチが好きですが、残念ながら、私はレガシーなデータベースで作業していて、次のエラーを受け取ります...複雑なタイプxは、プロパティZを介してエンティティタイプYを参照しています。円Refや何かの可能性を示していると仮定することしかできません。 – Lenny

+0

@Lenny - ToList()は、式からdbを削除する必要があります。しかし、EFマッピングを知っている人は?それは、プロキシ、怠惰な読み込みなどで何をすることができますか?どの行が失敗するのですか? – qujck

+0

これは役立つようにチェック... http://stackoverflow.com/questions/15438195/odata-exception-the-complex-type-webtools-order-refers-to-the-entity-type-webありがとう – Lenny

0

あなたが返す照会可能ではなくAutoMapperのdbContext.dbSet.Select(X =>新しいモデル{ID = x.Id})機構を介している場合。 Queryableで条件を適用すると、EF LINQプロバイダによって自動的に変換および評価されます。そうでなければ、式をModelプロパティに基づく式からEF_Classプロパティの式に変更するカスタムLINQプロバイダを作成する必要があります。

+1

をテストするためのいくつかのデータがあります。私がEFクラスを使用すると、リソースのURIであるナビゲーションプロパティを優先してidプロパティ(他のIDと一緒に)を隠すことができなくなります。それでも可能な唯一の方法は、いくつかの醜い部分クラスの作業や、EFクラスを生成するt4テンプレートの変更によるものです。私はこれについて間違っていますか?私は本当にEFクラスを共有すればよいですか? – Lenny

関連する問題