Castle Windsor IRepository パターンを使用して、LinqToSQL である DAL から抽象化するシステムを継承しました。
私が見ることができる主な問題は、IRepository が IEnumerable のみを実装していることです。そのため、最も単純なクエリでも、データテーブルからすべてのデータをロードして、単一のオブジェクトを返す必要があります。
現在の使用状況は以下の通り
using (IUnitOfWork context2 = IocServiceFactory.Resolve<IUnitOfWork>())
{
KpiFormDocumentEntry entry = context2.GetRepository<KpiFormDocumentEntry>().FindById(id, KpiFormDocumentEntry.LoadOptions.FormItem);
そして、これはラムダを使用してフィルタリングします。
public static KpiFormDocumentEntry FindById(this IRepository<KpiFormDocumentEntry> source, int id, KpiFormDocumentEntry.LoadOptions loadOptions)
{
return source.Where( qi => qi.Id == id ).LoadWith( loadOptions ).FirstOrDefault();
}
したがって、それは素晴らしい拡張メソッドになります。
私の質問は、どうすればこの同じインターフェイス/パターンなどを使用できるだけでなく、IQueryable を実装して LinqToSQL を適切にサポートし、パフォーマンスを大幅に向上させることができますか?
IRepository の現在の実装/インターフェイスは次のとおりです。
public interface IRepository<T> : IEnumerable<T> where T : class
{
void Add(T entity);
void AddMany(IEnumerable<T> entities);
void Delete(T entity);
void DeleteMany(IEnumerable<T> entities);
IEnumerable<T> All();
IEnumerable<T> Find(Func<T, bool> predicate);
T FindFirst(Func<T, bool> predicate);
}
そして、これは SqlClientRepository によって実装されます
public sealed class SqlClientRepository<T> : IRepository<T> where T : class
{
private readonly Table<T> _source;
internal SqlClientRepository(Table<T> source)
{
if( source == null ) throw new ArgumentNullException( "source", Gratte.Aurora.SHlib.labelText("All_TableIsNull",1) );
_source = source;
}
//removed add delete etc
public IEnumerable<T> All()
{
return _source;
}
public IEnumerator<T> GetEnumerator()
{
return _source.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
現時点での問題は、上記の例では、.Where が 'GetEnumerator' を呼び出しており、すべての行をメモリにロードしてから、必要な行を探していることです。
IQueryable を実装するように IRepository を変更すると、必要な 3 つのメソッドを実装できなくなります。これらは Table クラスで公開されていないためです。
SQLClientRepository をそのように定義するように変更する必要があると思います
public sealed class SqlClientRepository<T> : IQueryable<T>, IRepository<T> where T : class
そして、必要なメソッドを実装しますが、表クラスのプライベートメンバーであるため、式を渡す方法などを理解できません。
public override Type ElementType
{
get { return _source.ElementType; } //Won't work as ElementType is private
}
public override Expression Expression
{
get { return _source.Expression; } //Won't work as Expression is private
}
public override IQueryProvider Provider
{
get { return _source.Provider; } //Won't work as Provider is private
}
これを「ロード後にデータベース内のすべての行を反復処理する」から「select x where id=1」に移動することを本当に感謝しています!