我已经继承了一个系统,它使用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