Sim*_*mon 5 linq nhibernate specification-pattern repository-pattern eager-loading
我已经使用Linq实现了规范模式,如下所述https://www.packtpub.com/article/nhibernate-3-using-linq-specifications-data-access-layer
我现在想要增加急切负载的能力,并且不确定最好的方法.
链接示例中的通用存储库类:
public IEnumerable<T> FindAll(Specification<T> specification)
{
var query = GetQuery(specification);
return Transact(() => query.ToList());
}
public T FindOne(Specification<T> specification)
{
var query = GetQuery(specification);
return Transact(() => query.SingleOrDefault());
}
private IQueryable<T> GetQuery(
Specification<T> specification)
{
return session.Query<T>()
.Where(specification.IsSatisfiedBy());
}
Run Code Online (Sandbox Code Playgroud)
并且规范实现:
public class MoviesDirectedBy : Specification<Movie>
{
private readonly string _director;
public MoviesDirectedBy(string director)
{
_director = director;
}
public override
Expression<Func<Movie, bool>> IsSatisfiedBy()
{
return m => m.Director == _director;
}
}
Run Code Online (Sandbox Code Playgroud)
这很好用,我现在想要添加能够加载的能力.我理解NHibernate的热切加载可以通过在查询上使用Fetch来完成.
我正在寻找的是是否在规范中封装急切的加载逻辑或将其传递到存储库,以及实现此目的所需的Linq /表达式树语法(即如何完成它的示例).
一个可能的解决方案是扩展Specification类来添加:
public virtual IEnumerable<Expression<Func<T, object>>> FetchRelated
{
get
{
return Enumerable.Empty<Expression<Func<T, object>>>();
}
}
Run Code Online (Sandbox Code Playgroud)
并将 GetQuery 更改为:
return specification.FetchRelated.Aggregate(
session.Query<T>().Where(specification.IsSatisfiedBy()),
(current, related) => current.Fetch(related));
Run Code Online (Sandbox Code Playgroud)
现在您所要做的就是在需要时重写 FetchRelated
public override IEnumerable<Expression<Func<Movie, object>>> FetchRelated
{
get
{
return new Expression<Func<Movie, object>>[]
{
m => m.RelatedEntity1,
m => m.RelatedEntity2
};
}
}
Run Code Online (Sandbox Code Playgroud)
我刚刚编写的这个实现的一个重要限制是您只能获取与根实体直接相关的实体。
改进是支持任意级别(使用ThenFetch),这需要对我们使用泛型的方式进行一些更改(我曾经object允许轻松组合不同的实体类型)