Linq: leuk maar link

Zoals de titel al suggereert: ik vind Linq leuk op een maar na.

Laat ik eerst eens wat punten opnoemen die ik leuk en goed vind van Linq:

  • Het ziet er bekend uit
  • Type-Safe queries
  • Bruikbaar over meerdere bronnen
  • Uitbreidbaar


Laat mij deze punten eerst maar eens verduidelijken.

Linq ziet er bekend uit omdat het taaltje lijkt op SQL in een iets andere volgorde. Dus mensen zullen het snel begrijpen. Dat betekent ook dat mensen snel up-to-speed zijn om te helpen bij je project en dat is wel een pluspunt.

Omdat een compiler over je Linq queries gaat is het type-safe en dat is mooi. Geen gezeur meer met SQL tikken in een StringBuilder en deze dan uitvoeren om er tijdens het uitvoeren van je programma tegen een exceptie aan te lopen omdat je query niet goed was.

Linq werkt over meerdere bronnen. De meest voor de hand liggende is uiteraard Linq to SQL. Dit geeft je de mogelijkheid om Linq te gebruiken over je database. Uiteraard moet er dan wel een provider voor zijn die het ondersteund. Er zit in het Microsoft .NET Framework 3.5 ook een Linq to XML provider. Dit betekent niet meer stoeien met nodes maar gewoon je XPath query uitvoeren via Linq. Uiteraard is het collection framework van .NET ook uitgebreid met Linq mogelijkheden; dit heet Linq to Objects. Zo zullen er nog wel wat onderdelen in het framework zitten die ook Linq ondersteunen. Zelf ben ik alleen met deze onderdelen in aanraking gekomen.

Het is zelfs mogelijk om je eigen Linq provider te schrijven. Dit doe je door (onder andere) IQueryable te implementeren.

Het probleem
Als ontwikkelaar vind ik persoonlijk code completion een geweldig iets. Dit zorgt er voor dat je niet alle methoden en eigenschappen van elke Class uit je hoofd hoeft te kennen.
Nu is het probleem dat een Linq enabled object in samenwerking met code completion eigenlijk tegen je liegt.

Klein voorbeeld
Dit voorbeeld werkt (op ontbrekende onderdelen na).

var personen = from psn in contextPersonen
                     where psn.NAAM.Contains(strNaam)
                     select psn;
return personen.Take(100);

Deze code zorgt er voor dat 100 personen waar ‘strNaam’ voorkomt in de naam worden geretourneerd. Of niet?

Analyse
Zodra we deze code tikken en een punt achter het object personen neerzetten zegt Visual Studio dat er een reeks methoden op zitten die allemaal erg interessant zijn. De code complete toont alle mogelijkheden van IQueryable en niet noodzakelijkerwijs wat de Linq provider kan.
Maar het werkt wel. Onder water zal Linq, in dit voorbeeld, alle personen ophalen die de tekst van ‘strNaam’ bevatten in de naam. Dat zal Linq in Linq to Objects het laatste stapje uitvoeren: Take(100).
(Dit is overigens een fictief voorbeeld. Onze provider heeft wel Take maar dit is als voorbeeld wat makkelijker uit te leggen dat de problematiek die wij tegen kwamen).

Oftewel: Linq gaat transparant en zonder waarschuwing van de ene Linq provider naar de andere om je query te kunnen uitvoeren. Dat is mooi maar ook link.
In de ontwikkelomgeving zal dit dus prima werken totdat je gaat testen met een database waar velen male meer personen in de database staat. Want dan wordt bijna je hele tabel in je geheugen gelezen bij het invoeren van één letter.