Cela fait quelques années que j’utilise les ORM tel que “LINQ to SQL” et Entity Framework, cependant, il m’arrive encore d’être surpris de constater comment une requête LINQ est traduite en SQL.

Contexte

Prenons un exemple de table appelée “Customers” et contenant 2 champs :

  1. ID (NOT NULL)
  2. Name (NULL)

Si je désire récupérer les clients ayant un nom ou au contraire récupérer les clients n’ayant pas de nom, j’écrirai les deux requêtes LINQ suivantes :

var query = from cust in context.Customers
            where cust.name == "Carl"
            select cust;
var query = from cust in context.Customers
            where cust.name == null
            select cust;

La seconde requête, où on désire récupérer les employés n’ayant pas de nom, ne pose pas de problème car le SQL généré au niveau de la condition sera “WHERE name IS NULL”.

Problème

Un problème apparait lorsque la valeur de comparaison est stockée dans une variable :

string customerName = null;

var query = from cust in context.Customers
            where cust.name == customerName
            select cust;

Dans ce cas-ci, le code SQL généré est “WHERE name = NULL”, ce qui évidemment ne renverra rien.

Solution

Il est cependant possible de contourner ce problème, à condition d’en être conscient…

Pour Entity Framework, on utilisera ces écritures :

var query = from cust in context.Customers
            where (customerName == null ? cust.name == null : cust.name == customerName)
            select cust;
var query = from cust in context.Customers
            where (cust.name ?? "") == (customerName ?? "")
            select cust;

Il semblerait que ce problème soit enfin corrigé avec Entity Framework 4.5 suite aux insistances des développeurs.

En ce qui concerne LINQ to SQL, on retrouvera les mêmes syntaxes avec une supplémentaire que j’ai pas réussi à faire fonctionne avec Entity Framework :

var query = from cust in context.Customers
            where (customerName == null ? cust.name == null : cust.name == customerName)
            select cust;
var query = from cust in context.Customers
            where (cust.name ?? "") == (customerName ?? "")
            select cust;
var query = from cust in context.Customers
            where Object.Equals(cust.name, customerName) == true
            select cust;

Conclusion

Une fois de plus, je me suis fait avoir et le plus surprenant, c’est d’avoir passé autant de temps sans vraiment rencontrer clairement ce cas.

Soyez donc prudents Winking smile

Have fun!