EF7の述語にパラメータを使用するときにToListAsync()を使用できないのはなぜですか?

asp.net-core c# entity-framework-core

質問

私は現在、ASP.VNextアプリケーションのリポジトリパターンを実装しています 。私はメソッドが非同期でフィルタリング可能であることを望みます。だから私は、次のインターフェイスメソッドを考案しました:

Task<TEntity> GetOneAsync(Func<TEntity,bool> predicate);

このように(プライベートなDbContextインスタンスのctx使って)実装したいと考えています:

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{
    // compiler error
    return await ctx.MyEntities.Where(predicate).FirstOrDefaultAsync();
}

しかし、私はFirstOrDefaultAsync()を次のように述語をハードコーディングするときにしか使用できません:

return await ctx.MyEntites.Where(e => e.Id == 1).FirstOrDefaultAsync();

述語を渡すとき、私はasyncオプションなしでFirstOrDefault()だけを取得するので、私のメソッドを非同期にするためには、

public async Task<MyEntity> GetOneAsync(Func<MyEntity,bool> predicate) 
{
    //save to a local variable to prevent calling a disposed DbContext
    var entities = await Task.Run(() => ctx.Contracts.Where(predicate).FirstOrDefault());
    return entities;
}

私はこれに関する2つの質問があります:

  1. 述語を渡すときにFirstOrDefaultAsync()メソッドにアクセスできないのはなぜですか?

  2. await Task.Run(synchronousMethod)FirstOrDefaultAsync()呼び出しと同じ動作をするのをawait Task.Run(synchronousMethod)いる私の解決策はありますか?

受け入れられた回答

FirstOrDefaultAsyncは、 IQueryable<T>拡張メソッドとして定義されています。

ctx.MyEntities.Where(e => e.Id == 1)は、 IQueryable<MyEntity>返します。

ctx.MyEntities.Where(predicate)は、 Queryable.Whereではなく、 Enumerable.Where拡張メソッドを呼び出すため、 IEnumerable<MyEntity>返しQueryable.Where

それを機能させるには、 predicateFunc<MyEntity, bool>からExpression<Func<MyEntity, bool>>ます。これは、 predicateがもはやあなたが望む結果を与える関数ではなく、その関数の説明で、Entity FrameworkがSQLに変換できることを意味します。

また、タスク内でFunc<MyEntity, bool>を使用しても、同じ動作は行われません。これは、フィルタリングを行わずにdbサーバからローをロードし、一致が見つかるまでdbクライアントのすべてを評価します。それは多くのオーバーヘッドを追加します。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ