Question

J'ai mis le modèle de cahier des charges avec LINQ comme indiqué ici https://www.packtpub.com/article/nhibernate-3-using-linq-specifications-data-access-layer

Je veux maintenant ajouter la capacité de charge avide et ne suis pas sûr de la meilleure façon de s'y prendre.

La classe référentiel générique dans l'exemple lié:

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

Et la mise en œuvre des spécifications:

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

Cela fonctionne bien, je veux maintenant ajouter la capacité d'être en mesure de charger avide. Je comprends NHibernate chargement désireux peut être fait en utilisant Fetch sur la requête.

Ce que je suis à la recherche est de savoir si à encapsulent la logique de chargement désireux dans le cahier des charges ou de passer dans le référentiel, ainsi que la syntaxe de l'arbre Linq / expression nécessaire pour y parvenir (par exemple un exemple de la façon dont il serait fait) .

Était-ce utile?

La solution

Une solution possible serait d'étendre la classe de spécification d'ajouter:

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

Et le changement GetQuery à quelque chose comme:

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

Maintenant, tout ce que vous avez à faire est prioritaire FetchRelated en cas de besoin

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

Une limitation importante de cette mise en œuvre, je viens d'écrire est que vous ne pouvez chercher des entités qui sont directement liés à l'entité racine.

amélioration Un serait de soutenir des niveaux arbitraires (utilisant ThenFetch), ce qui nécessiterait des changements dans la façon dont nous travaillons avec les génériques (je object pour permettre la combinaison de différents types d'entités facilement)

Autres conseils

Vous ne voulez pas mettre l'appel fetch () dans le cahier des charges, car il est pas nécessaire. Spécification est juste pour limiter les données qui peuvent ensuite être partagées entre les différentes parties de votre code, mais les autres parties pourraient avoir des besoins radicalement différents dans les données qu'ils souhaitent présenter à l'utilisateur, ce qui est la raison pour laquelle à ces points que vous ajouteriez votre fetch.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top