Domanda

Ho implementato il modello specifica con LINQ come descritto qui https://www.packtpub.com/article/nhibernate-3-using-linq-specifications-data-access-layer

Ora voglio aggiungere la possibilità di carico ansiosi e sono sicuro circa il modo migliore per andare su di esso.

La classe repository generica nell'esempio collegato:

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

E l'attuazione specifica:

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

Questo funziona bene, io ora voglio aggiungere la capacità di essere in grado di caricare ansioso. Capisco NHibernate ansioso di carico può essere fatto utilizzando Fetch su la query.

Quello che sto cercando è se per incapsulare la logica eager loading all'interno della specificazione o di passarlo nel repository, e anche il / la sintassi albero Linq espressione necessaria per raggiungere questo obiettivo (vale a dire un esempio di come sarebbe stato fatto) .

È stato utile?

Soluzione

Una possibile soluzione potrebbe essere quella di estendere la classe specifica di aggiungere:

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

E il cambiamento GetQuery a qualcosa di simile:

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

Ora tutto ciò che dovete fare è di override FetchRelated quando necessario

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

Un importante limitazione di questa implementazione che ho appena scritto è che è possibile recuperare solo le entità che sono direttamente correlati all'entità root.

Un miglioramento sarebbe sostenere livelli arbitrari (usando ThenFetch), che richiederebbe alcuni cambiamenti nel modo di lavorare con i generici (ho usato object permettere combinando diversi tipi di entità facilmente)

Altri suggerimenti

Non si vorrebbe mettere la chiamata Fetch () nella specifica, perché non è necessario. Specifica è solo per limitare i dati che possono poi essere condivisi tra diverse parti del codice, ma quelle altre parti potrebbe avere esigenze drasticamente diverse in quanto i dati che vogliono presente per l'utente, che è il motivo per cui in questi punti si dovrebbe aggiungere la tua Fetch dichiarazioni.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top