5

预先加载我实现了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()); 
} 

而且实现了规范:

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; 
} 
} 

这是工作好了,我现在要添加到能够急于负载的能力。我明白NHibernate的急切加载可以通过在查询上使用Fetch来完成。

我在寻找的是在规范中封装加载逻辑还是将它传递到存储库中,还需要Linq /表达式树语法来达到这个目的(例如它将如何完成)。

回答

3

一个可能的解决方案将是扩展的规范类补充:

public virtual IEnumerable<Expression<Func<T, object>>> FetchRelated 
{ 
    get 
    { 
     return Enumerable.Empty<Expression<Func<T, object>>>(); 
    } 
} 

,并更改GetQuery喜欢的东西:

 return specification.FetchRelated.Aggregate(
      session.Query<T>().Where(specification.IsSatisfiedBy()), 
      (current, related) => current.Fetch(related)); 

现在你要做的就是覆盖FetchRelated需要

public override IEnumerable<Expression<Func<Movie, object>>> FetchRelated 
{ 
    get 
    { 
     return new Expression<Func<Movie, object>>[] 
        { 
         m => m.RelatedEntity1, 
         m => m.RelatedEntity2 
        }; 
    } 
} 

我刚刚写的这个实现的一个重要限制是t您只能获取与根实体直接相关的实体。

的改善将支持任意水平(使用ThenFetch),这将需要的方式有些变化,我们使用泛型(我以前object,以便轻松组合不同的实体类型)

+0

这当然是一个解决方案,但这是一个责任混合(封装查询和获取策略)。这就是存储库模式很弱的原因。 – jason 2010-12-06 16:27:54

1

你不会想工作将Fetch()调用放入规范中,因为它不是必需的。规范只是用于限制可以在代码的许多不同部分之间共享的数据,但其他部分对于要向用户展示什么数据的需求可能完全不同,这就是为什么在这些点上添加您的获取语​​句。