2010-10-12 6 views
1

Tenir compte suivant les requêtes LINQ-à-NHibernate:requête LINQ ne fonctionne pas sans .ToList()

var q1 = from se in query.ToList<SomeEntity>() 
    where 
    prop1 == "abc" 
    select se; 

var q2 = from se in q1 
    where 
    m1(se.prop2) == "def" 
    select se; 

q2 ne fonctionnera pas avec l'erreur: "La méthode n'est pas mis en œuvre m1". Mais quand remplacer q2 avec requête suivante, tout se passe bien:

var q2 = from se in q1.ToList<SomeEntity>() 
    where 
    m1(se.prop2) == "def" 
    select se; 

Pourquoi cela se produit? Comment puis-je faire fonctionner la première requête? Est-ce quelque chose qui arrive pour LINQ-à-NHibernate seulement ou arrive dans toutes les requêtes LINQ?

Répondre

3

Parce que le fournisseur LINQ ne peut pas traduire la méthode m1 en une instruction SQL compatible. En appelant ToList<SomeEntity>(), vous lisez le tout en mémoire puis en utilisant LINQ to Objects pour filtrer (et puisque la requête n'est pas traduite en SQL dans ce cas, il n'y a aucun problème à exécuter la requête).

Malheureusement, il n'y a pas de moyen facile de faire fonctionner la première requête. Si vous avez vraiment besoin d'utiliser m1 pour filtrer les résultats, vous devez d'abord lire les éléments dans la mémoire.

Il ne s'agit pas seulement d'une limitation LINQ to nHibernate. Cela se produit dans toute situation où un fournisseur LINQ utilise Expression Trees pour convertir votre code dans une autre langue (dans ce cas, il essaie de convertir votre code C# en instructions SQL, ce qui est la même chose que LINQ to SQL et Entity Framework).

+3

Ceci est correct. Cependant, NHibernate 3 ** ** vous permet d'étendre le fournisseur LINQ pour supporter n'importe quel appel de méthode (bien sûr, vous devez savoir comment créer un arbre HQL à partir de celui-ci). Voir http://fabiomaulo.blogspot.com/2010/07/nhibernate-linq-provider-extension.html –

+0

@Diego Mijelshon: fonctionnalité étonnante dans NHibernate 3, merci beaucoup d'informer. –

1

Vraisemblablement, la méthode m1 n'a pas de traduction en SQL (au moins, le fournisseur NHibernate LINQ ne peut pas comprendre comment). Lorsque vous n'avez pas le ToList, NHibernate essaie de comprendre comment convertir m1 en SQL. Lorsque vous faites le ToList, NHibernate ne joue plus de rôle et ses LINQ-to-Objects peuvent gérer la requête. Ceci est spécifique aux ORM qui activent LINQ; LINQ-to-SQL et EF subiront des destins similaires.

1

Je dirais que votre requête q2 d'origine est en cours de traduction dans une arborescence d'expression et que lorsque NHibernate essaie de l'analyser, elle trouve que la méthode ne fait pas partie de son implémentation. La conversion de la requête en une collection d'abord avec ToList() utilise la fonctionnalité LINQ de la liste qui peut prendre en charge la méthode m1.

0

Je ne connais pas NHibernate, mais cela fonctionnerait-il?

var q2 = q1.where (x => m1(x.prop2) == "def"); 
Questions connexes