我已經繼承了一個系統,它使用Castle Windsor IRepository模式從LinqToSQL的DAL中抽象出來。更改IRepository以支持IQueryable(LINQtoSQL查詢)
我可以看到的主要問題是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();
}
}
目前的問題是執行,在我們的例子上面,調用'GetEnumerator'時,它會將所有行加載到內存中,然後查找我們需要的行。
如果我更改IRepository來實現IQueryable,我無法實現所需的三個方法,因爲這些方法在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
}
的任何幫助非常感激,從「加載它後遍歷數據庫中的每一行」移動這「選擇x其中id = 1」!
謝謝你。實際上,這正是我在某些地方所做的,但在這方面,我希望獲得好處,而不必重寫我們已經完成的所有事情。我會看看你的文章。謝謝。 – adudley
還有其他問題嗎? – jgauffin