私は通常、汎用リポジトリを使用してEFクエリを定型化するため、限られたコードを記述し、キャッシュも使用する必要があります。リポジトリのソースコードはここにあります。
コード内のバックボーンクエリは、以下のクエリです。FromCache<T>()
は、ラムダ式の文字列化された表現をキーとして使用してクエリを格納するためにIEnumerable<T>
を利用する拡張メソッドです。HttpContext.Cache
public IQueryable<T> Any<T>(Expression<Func<T, bool>> expression = null)
where T : class, new()
{
// Check for a filtering expression and pull all if not.
if (expression == null)
{
return this.context.Set<T>()
.AsNoTracking()
.FromCache<T>(null)
.AsQueryable();
}
return this.context.Set<T>()
.AsNoTracking<T>()
.Where<T>(expression)
.FromCache<T>(expression)
.AsQueryable<T>();
}
これはすべて機能しますが、次のようなクエリを作成する場合は、関連するテーブルのN+1の問題が発生します。
var posts = this.ReadOnlySession.Any<Post>(p => p.IsDeleted == false)
.Include(p => p.Author);
Include()
キャッシュするためにすでに実行されているため、クエリには影響しません。
これで、ナビゲーションプロパティの仮想プレフィックスを削除することで、Entity Frameworkにモデル内での積極的な読み込みを強制できることがわかりましたが、実行するクエリの種類を予測できないため、それを行うのは間違った場所のように感じます。私には、コントローラークラスでやっていることのように感じます。私が疑問に思っているのは、インクルードのリストをAny<T>()
メソッドに渡して、呼び出しを行うときに反復できるかどうかです。