目前,我们正在为我们暴露IQueryable(使用NH3 linq支持)的所有实体使用通用存储库,然后由我们的服务层使用它来构建特定查询。
我现在需要急切地加载一个关联。有什么办法可以公开IQueryable并传入可选的fetch表达式吗?我看到的问题是Fetch必须在表达式中排在最后(根据http://mikehadlow.blogspot.com/2010/08/nhibernate-linq-eager-fetching.html)。
我很好奇其他人是如何实现这一目标的。
我确实考虑过将Linq规范传递给存储库,以便在调用Fetch之前对它们进行评估。但是我仍然需要一些传递Fetch表达式的方法。
由于 本
答案 0 :(得分:3)
我使用我的FindOne
和FindAll
存储库调用的重载来实现这一点......如下所示:
Function FindOne(ByVal spec As ILinqSpecification(Of T)) As T
Function FindOne(ByVal spec As ILinqSpecification(Of T), ByVal strategy As IFetchingStrategy(Of T)) As T
Function FindAll(ByVal spec As ILinqSpecification(Of T)) As IQueryable(Of T)
Function FindAll(ByVal spec As ILinqSpecification(Of T), ByVal strategy As IFetchingStrategy(Of T)) As IQueryable(Of T)
等。
也许不是最干净的方法,但它确实起到了作用。我不确定这是否仍然是trunk linq提供程序的问题,但我也可以根据我是否在FindAll
场景中决定是否将不同的结果转换器应用于我的结果提取策略包含一个集合。
我的规范和提取策略实现基于ncommon项目中提供的那些。
作为参考,我的完整通用“只读”存储库界面如下:
Public Interface IReadOnlyRepositoryWithTypedId(Of T As IEntityWithTypedId(Of IdT), IdT)
Function LoadById(ByVal id As IdT) As T
Function GetById(ByVal id As IdT) As T
Function FindOne(ByVal spec As ILinqSpecification(Of T)) As T
Function FindOne(ByVal spec As ILinqSpecification(Of T), ByVal strategy As IFetchingStrategy(Of T)) As T
Function GetCount() As Integer
Function GetCount(ByVal spec As ILinqSpecification(Of T)) As Integer
Function HasAny(ByVal spec As ILinqSpecification(Of T)) As Boolean
Function FindAll(ByVal spec As ILinqSpecification(Of T)) As IQueryable(Of T)
Function FindAll(ByVal spec As ILinqSpecification(Of T), ByVal strategy As IFetchingStrategy(Of T)) As IQueryable(Of T)
Function FindAll() As IQueryable(Of T)
Function FindAll(ByVal strategy As IFetchingStrategy(Of T)) As IQueryable(Of T)
End Interface
答案 1 :(得分:2)
我最终提出的解决方案是将以下内容添加到我的通用存储库界面:
public IEnumerable<T> FindAll<TRelated>(Specification<T> specification, Expression<Func<T, TRelated>> fetchExpression);
NHibernate的实现是:
public IEnumerable<Product> FindAll<TRelated>(Specification<Product> specification, Expression<Func<Product, TRelated>> fetchExpression) {
return session.Query<Product>()
.Where(specification.IsSatisfiedBy())
.Fetch(fetchExpression);
}
我正在使用Linq Specs(http://linqspecs.codeplex.com)。
有关完整详情,请参阅http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Eager-loading-with-NHibernate-LINQ.aspx
然而,正如Dan在评论中指出的那样,this看起来似乎是一种更好的抽象方式。
答案 2 :(得分:2)
我做的是这样的事(抱歉,C#): 首先,界面:
IQueryable<T> All<T>(params Expression<Func<T, Object>> [] fetchPaths);
至于实施:
public IQueryable<T> All<T>(params Expression<Func<T, Object>> [] fetchPaths)
{
var queryable = this.session.Query<T>();
foreach (var fetchPath in fetchPaths)
{
queryable = queryable.Fetch(fetchPath);
}
return queryable;
}