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()調用放入規範中,因爲它不是必需的。規範只是用於限制可以在代碼的許多不同部分之間共享的數據,但其他部分對於要向用戶展示什麼數據的需求可能完全不同,這就是爲什麼在這些點上添加您的獲取語​​句。