Sco*_*ock 15 repository linq-to-nhibernate eager-loading
我正在使用一个暴露IQueryable<T>这样的通用存储库:
public IQueryable<T> AllEntities
{
get
{
return session.Query<T>();
}
}
Run Code Online (Sandbox Code Playgroud)
我可以像这样查询:
var results =
(from e in repository.AllEntities
where e.SomeProperty == "some value"
select e).ToList();
Run Code Online (Sandbox Code Playgroud)
但是,如果T有父母和祖父母实体并且我想急切地加载它们,我必须这样做:
var results =
(from e in repository.AllEntities
where e.SomeProperty == "some value"
select e)
.Fetch(x => x.Parent)
.ThenFetch(x => x.Grandparent)
.ToList();
Run Code Online (Sandbox Code Playgroud)
这工作,但.Fetch并.ThenFetch都Linq2Nhibernate特定扩展方法,这是造成两个问题:
我必须using NHibernate.Linq;在我的文件顶部包含一个声明.但是,在我正在进行此查询时,它应该是与实现无关的.
当我尝试对此进行单元测试时,.Fetch和我的模拟存储库提供的.ThenFetch方法相比,和方法失败IQueryable<T>了.
如何将这些内容包装在我的IRepository<T>界面内或某些通用扩展方法中?
更新:
到目前为止,我所提出的是将其添加到我的存储库界面:
IQueryable<T> EagerLoadParent<U>(IQueryable<T> query,
Expression<Func<T, U>> parentExpression);
IQueryable<T> EagerLoadParent<U, V>(IQueryable<T> query,
Expression<Func<T, U>> parentExpression,
Expression<Func<U, V>> grandparentExpression);
Run Code Online (Sandbox Code Playgroud)
...这对我的NHibernate存储库实现:
public IQueryable<T> EagerLoadParent<U>(IQueryable<T> query,
Expression<Func<T, U>> parentExpression)
{
return query
.Fetch(parentExpression);
}
public IQueryable<T> EagerLoadParent<U, V>(IQueryable<T> query,
Expression<Func<T, U>> parentExpression,
Expression<Func<U, V>> grandparentExpression)
{
return query
.Fetch(parentExpression)
.ThenFetch(grandparentExpression);
}
Run Code Online (Sandbox Code Playgroud)
此API的使用者现在执行此操作:
var query =
(from e in repository.AllEntities
where e.SomeProperty == "some value"
select e);
var results = repository
.EagerLoadParent(query, e => e.Parent, p => p.Grandparent)
.ToList();
Run Code Online (Sandbox Code Playgroud)
但这缺乏我更喜欢的好的扩展方法语法.我正在寻找更接近.Fetch和.ThenFetch语法的东西.
gui*_*ido 14
经过一番调查后,我认为我有一个方法:只需密切关注NHibernate.Linq实现,以便拥有自己的实现,并避免在客户端代码中明确的NHibernate.Linq依赖.你只需要非常紧密地重现
NHibernate.Linq.EagerFetchingExtensionMethods课程.
它需要一个接口:IFetchRequest,一个FetchRequest实现的类IFetchRequest和一个EagerFetch实现扩展方法的静态类.这是一种类的克隆NHibernate.Linq.EagerFetchingExtensionMethods.
只需定义:
public interface IFetchRequest<TQueried, TFetch> : IOrderedQueryable<TQueried> {}
Run Code Online (Sandbox Code Playgroud)
这模仿 NHibernate.Linq.INhFetchRequest<TQueried, TFetch>
然后定义一个实现:
public class FetchRequest<TQueried, TFetch> : IFetchRequest<TQueried, TFetch> {
#region IEnumerable<TQueried> Members
public IEnumerator<TQueried> GetEnumerator(){
return NhFetchRequest.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return NhFetchRequest.GetEnumerator();
}
#endregion
#region IQueryable Members
public Type ElementType {
get { return NhFetchRequest.ElementType; }
}
public System.Linq.Expressions.Expression Expression {
get { return NhFetchRequest.Expression; }
}
public IQueryProvider Provider {
get { return NhFetchRequest.Provider; }
}
#endregion
public FetchRequest(INhFetchRequest<TQueried, TFetch> nhFetchRequest){
NhFetchRequest = nhFetchRequest;
}
public INhFetchRequest<TQueried, TFetch> NhFetchRequest { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
这个只是拥有一个nHibernate实现,并将每个方法转发给该成员.
最后:
public static class EagerFetch {
/*
replacing methods from NHibernate.Linq.EagerFetchingExtensionMethods
private static INhFetchRequest<TOriginating, TRelated> CreateFluentFetchRequest<TOriginating, TRelated>(MethodInfo currentFetchMethod, IQueryable<TOriginating> query, LambdaExpression relatedObjectSelector);
public static INhFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector);
public static INhFetchRequest<TOriginating, TRelated> FetchMany<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector);
public static INhFetchRequest<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>(this INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector);
public static INhFetchRequest<TQueried, TRelated> ThenFetchMany<TQueried, TFetch, TRelated>(this INhFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector);
*/
public static IFetchRequest<TOriginating, TRelated> Fetch<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, TRelated>> relatedObjectSelector){
var fetch = EagerFetchingExtensionMethods.Fetch(query, relatedObjectSelector);
return new FetchRequest<TOriginating, TRelated>(fetch);
}
public static IFetchRequest<TOriginating, TRelated> FetchMany<TOriginating, TRelated>(this IQueryable<TOriginating> query, Expression<Func<TOriginating, IEnumerable<TRelated>>> relatedObjectSelector){
var fecth = EagerFetchingExtensionMethods.FetchMany(query, relatedObjectSelector);
return new FetchRequest<TOriginating, TRelated>(fecth);
}
public static IFetchRequest<TQueried, TRelated> ThenFetch<TQueried, TFetch, TRelated>(this IFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, TRelated>> relatedObjectSelector){
var impl = query as FetchRequest<TQueried, TFetch>;
var fetch = EagerFetchingExtensionMethods.ThenFetch(impl.NhFetchRequest, relatedObjectSelector);
return new FetchRequest<TQueried, TRelated>(fetch);
}
public static IFetchRequest<TQueried, TRelated> ThenFetchMany<TQueried, TFetch, TRelated>(this IFetchRequest<TQueried, TFetch> query, Expression<Func<TFetch, IEnumerable<TRelated>>> relatedObjectSelector){
var impl = query as FetchRequest<TQueried, TFetch>;
var fetch = EagerFetchingExtensionMethods.ThenFetchMany(impl.NhFetchRequest, relatedObjectSelector);
return new FetchRequest<TQueried, TRelated>(fetch);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2804 次 |
| 最近记录: |