私も同じことを経験しました。リポジトリ パターンを実装するとき、DbSet< T > を公開せずに、DbSet< T > が実装する IQueryable< T > および IEnumerable< T > を使用できるようにしたいと考えていました (古き良き情報隠蔽)。
したがって、すべての IQueryable / IEnumerable 関数が、リポジトリ内の DbSet< T > の対応する関数を呼び出せるようにするだけで十分だと考えました。
今日まで、私のすべての IQueryable< T > 関数にはこれで十分でした。今日、 IQueryable.Include を除いて、あなたが説明したのと同じ問題があることを発見しました。コンパイラ エラーはありませんが、データは読み込まれません。
広範な結果の後、その理由は MSDN のQueryableExtensions.Include Method (IQueryable, String)の説明に記載されていることがわかりました
この拡張メソッドは、ソース IQueryable オブジェクトの Include(String) メソッドが存在する場合、そのメソッドを呼び出します。ソース IQueryable に一致するメソッドがない場合、このメソッドは何もしません。
したがって、対応する DbSet リポジトリを呼び出す一致する include ステートメントをリポジトリに記述するだけで済みました。IQueryable / IEnumerable 関数は、DbSet の対応する関数を呼び出すだけです。
public class Repository<T> :
System.Linq.IQueryable<T>, System.Collections.Generic.IEnumerable<T>,
System.Linq.IQueryable, System.Collections.IEnumerable
where T : class, new()
{
public Repository(DbContext dbContext)
{
this.dbContext = dbContext;
this.dbSet = dbContext.Set<T>();
}
public readonly DbSet<T> dbSet;
private readonly DbContext dbContext;
public virtual DbQuery<T> Include(string path)
{
return this.dbSet.Include(path);
}
// other Repository functions: Find / Add / Update / Remove etc
完全を期すために、IQueryable / IEnumerable の実装:
#region IQueryable
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return ((IQueryable<T>)this.dbSet).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)this.dbSet).GetEnumerator();
}
Type IQueryable.ElementType
{
get { return ((IQueryable<T>)this.dbSet).ElementType; }
}
System.Linq.Expressions.Expression IQueryable.Expression
{
get { return ((IQueryable)this.dbSet).Expression; }
}
IQueryProvider IQueryable.Provider
{
get { return ((IQueryable)this.dbSet).Provider; }
}
#endregion IQueryable
現在、次のように動作し、アドレスが含まれています。
using (MyDbContext dbContext = new MyDbContext(...))
{
Repository<Customer> customers = new Repository<Customer>(dbContext);
var happyCustomers = customers
.Include(customer => customer.Address)
.Where(customer => customer.IsHappy);
Show(happyCustomers);
}