.NET LINQ from Scratch

Als softwareontwikkelaars besteden we veel tijd aan het extraheren en weergeven van gegevens uit veel verschillende gegevensbronnen. Of het nu gaat om een ​​XML-webservice of een complete relationele database, we zijn gedwongen verschillende methoden voor gegevenstoegang te leren. Zou het niet geweldig zijn als de toegangsmethode hetzelfde was voor alle gegevensbronnen? Nou, we hebben geluk, want vanaf de release van C # 3.0 en het .NET 3.5 Framework is LINQ de game voor altijd gaan veranderen.

Zelfstudiedetails

  • Inleiding tot LINQ-syntaxis
  • Projecties met LINQ
  • Gegevens verfijnen
  • Standaard operatoren

Overzicht van huidige gegevenstoegang

Op het .NET-platform gebruiken en gebruiken we nog steeds ADO.NET
voor toegang tot verschillende gegevensbronnen. De open-sourcecommunity heeft ook voorzien
de ontwikkelaars met een aantal alternatieven.

Language Integrated Query is de nieuwe toevoeging aan .NET
familie en zoals de naam doet vermoeden, is het de soort datatoegang in de querystijl die
wordt volledig ondersteund door de taal om de manier waarop we toegang krijgen tot gegevens effectief te verenigen
en om ons leven gemakkelijker te maken. LINQ kan een aantal verschillende bronnen targeten, namelijk Oracle,
MSSQL, XML en een paar andere, maar voorlopig zullen we ons concentreren op de meest elementaire van
allemaal, LINQ to Objects.

LINQ to Objects

Normaal gesproken om de gegevens in onze lijsten te verwerken en te verfijnen
en verschillende andere datastructuren, hebben we ofwel de 'foreach'-lus of een andere gebruikt
type looping-methode om de objecten te doorlopen en ze één voor één te verwerken
een volgens een of andere voorwaarde. Dit is prima, maar eerlijk gezegd vereist dit veel
basiscodering die we allemaal wensen dat we niet hoefden te schrijven. In wezen hebben we het moeten vertellen
compiler elk detail van het proces om de gegevens te manipuleren.

Dit is precies waar LINQ het beste schijnt. Wat LINQ ons toestaat
doen is om de compiler gewoon te vertellen wat we willen uitvoeren en de compiler te laten werken
de beste manier om dat ook daadwerkelijk te bereiken. Als je eerder de SQL-syntax hebt gebruikt, de enorme gelijkenissen
tussen LINQ en alle dialecten van SQL zal het eerste zijn dat je zult opvallen.
Net als SQL ondersteunt LINQ ook de "select", "from", "where", "join", "group by"
en 'volgorde voor' zoekwoorden. Hier is een eenvoudig voorbeeld van een query op een lijst met objecten:

Lijst initialisatie:

 Lijst ListOfCars = nieuwe lijst() new Car name = "Toyota", owner = "Alex", model = 1992, new Car name = "Mitsubishi", owner = "Jeff", model = 2005, new Car name = "Land Rover ", owner =" Danny ", model = 2001, new Car name =" BMW ", owner =" Danny ", model = 2006, new Car name =" Subaru ", owner =" Smith ", model = 2003;

De vraag:

 IEnumerable QueryResult = uit auto in ListOfCars selecteer auto;

Het eerste deel van de voorgaande code vult eenvoudig een lijst in
met vier exemplaren van de klasse 'Auto'. Het volgende deel van de code maakt echter gebruik van de
"van" en "selecteer" trefwoorden om een ​​groep objecten te selecteren. Het grootste verschil
tussen SQL en LINQ is dat het trefwoord "from" vóór de "select" komt
sleutelwoord, omdat we eerst het object moeten definiëren waarop we willen werken. Tenslotte
de "select" -clausule vertelt de compiler wat we willen extraheren in deze query. Bovenstaande
code haalt gewoon alles uit de lijst en wijst het toe aan de "QueryResult"
veranderlijk.

Wanneer we dingen van objecten (LINQ tot Objecten) vragen naar onze
query's retourneren altijd een "IEnumrable"lijst met objecten
"IEnumerable" type is het soort lijst dat de enumerator blootstelt, welke
ondersteunt een eenvoudige iteratie over een niet-generieke verzameling, en
is het type van elk item in de lijst.
Maak je geen zorgen als je niet bekend bent met "tellers" en "generieken". Net
onthoud dat het resultaat van LINQ-query's altijd een verzameling van gegevens is
structuur die het mogelijk maakt er doorheen te itereren met behulp van een lus zoals getoond
blaten:

 foreach (Auto in QueryResult) Console.WriteLine (auto.name);

We hebben geleerd dat LINQ altijd dezelfde verzamelstructuur retourneert
naar andere lijsten. De LINQ-query wordt echter niet uitgevoerd totdat het resultaat is
toegankelijk via een ander stuk code, zoals de bovenstaande 'foreach'-lus. Dit is om
sta ons toe om de query continu te definiëren zonder de overhead door opnieuw te evalueren
elke nieuwe stap in de query.

projecties

Tot zover goed; maar meestal zullen onze vragen nodig zijn
om meer complex te zijn; dus laten we proberen gegevens te projecteren. In SQL betekent projectie selecteren
de naam van de kolom (men) van tabel (len) die men wenst te zien verschijnen in het resultaat
van de vraag. In het geval van LINQ to Objects, zal het uitvoeren van Projectie resulteren
in een ander queryresultaattype dan het type object dat we uitvoeren
query op.

Er zijn twee soorten projecties die we kunnen doen. We kunnen
voer een projectie uit op basis van een bestaand objecttype, of ga volledig
de andere manier door anonieme types te gebruiken. Het volgende voorbeeld is van de eerste
soort:

 IEnumerable QueryResult = uit auto in ListOfCars selecteer nieuwe CarOwner owner_name = car.owner;

In de voorgaande code wordt het type queryresultaat als gedeclareerd
, wat anders is , het type dat de 'ListOfCar'-variabele initialiseert met. Wij hebben
heeft ook het "nieuwe" sleutelwoord gebruikt en enkele opdrachten in de kronkel gedaan
beugels. In de bovenstaande code vertelt het gebruik van "select" met het "nieuwe" sleutelwoord de
compiler om een ​​nieuw 'CarOwner'-object te instantiëren voor elke invoer in het queryresultaat.
Ook door waarden toe te wijzen aan het nieuwe type hebben we elke instantie geïnitialiseerd
van de klasse 'CarOwner'.

Desalniettemin, als u nog niet een type heeft gedefinieerd
gebruik, kunt u nog steeds projecties uitvoeren met behulp van anonieme typen.

Projecties met behulp van anonieme typen

Het zou een groot gedoe zijn als je voor elke projectie was
gedwongen om een ​​nieuw type te maken. Dat is de reden waarom, vanaf C # 3.0, ondersteuning voor Anonymous
typen zijn aan de taal toegevoegd. Een anoniem type wordt gedeclareerd met behulp van de "var"
trefwoord. Het vertelt de compiler dat het type variabele tot dan onbekend is
het is voor de eerste keer toegewezen.

 var QueryResult = uit auto in ListOfCars selecteer nieuw car_name = car.name, owner_name = car.owner; foreach (var entry in QueryResult) Console.WriteLine (entry.car_name);

Het bovenstaande is een voorbeeld van het uitvoeren van een query met Anoniem
types. De enige catch om op te letten is dat de compiler dat niet zal doen
toestaat dat anonieme typen van methoden worden teruggestuurd.

Toegang tot de eigenschappen van een anoniem type is eenvoudig. In Visual Studio 2008, de code
Voltooiing / Intellisense somt ook de eigenschappen op die zijn blootgesteld door het anonieme type.

Gegevens verfijnen

Meestal als onderdeel van de LINQ-query, moeten we ook de
queryresultaat door een voorwaarde op te geven. Net als SQL gebruikt LINQ ook het "waar"
om de compiler te vertellen welke voorwaarden aanvaardbaar zijn.

 IEnumerable QueryResult = uit auto in ListOfCars waarbij car.name == "Subaru" auto selecteren;

De voorgaande code demonstreert het gebruik van de "where" -clausule en
de te volgen toestand. Om meerdere voorwaarden verder te definiëren, ondersteunt LINQ
de 'en' (&& amp) en 'of' (||) constructies. Het "where" -gedeelte van de query moet altijd een zijn
Booleaanse expressie, anders zal de compiler klagen.

Bestel door

Bij het opvragen van objecten is het mogelijk om op de query te vertrouwen
doelwit dat al is gesorteerd. Als dat niet het geval is, kan LINQ dat regelen
door de "order door" -clausule te gebruiken die ervoor zorgt dat het resultaat van uw vraag is
goed gesorteerd.

 IEnumerable QueryResult = uit auto in ListOfCars orderby car.model select car;

Als u de bovenstaande code uitvoert, ziet u dat het resultaat van de
query wordt in oplopende volgorde gesorteerd. U kunt de volgorde wijzigen door "oplopend" en "aflopend" te gebruiken
sleutelwoorden en wijzig de volgorde door meer dan één veld te specificeren om te sorteren
door. De volgende code laat zien hoe:

 IEnumerable QueryResult = uit auto in ListOfCars orderby car.model aflopende geselecteerde auto;

Groepering

LINQ maakt het ook mogelijk om het queryresultaat te groeperen met de waarde van a
specifieke eigenschap zoals getoond in dit voorbeeld:

 var QueryResult = van auto in ListOfCars groepswagen per auto.eigenaar in carOwnersGroep selecteren carOwnersGroup.Key;

Zoals u kunt zien, ondersteunt LINQ de "group by" -clausule
specificeer welk object en door welke eigenschap te groeperen. Het "in" -woord zal dat doen
sta ons toe om te projecteren op een groepeerresultaat dat toegankelijk is voor de "Sleutel"
eigendom.

Doet mee

LINQ ondersteunt het samenvoegen van gegevens uit verschillende collecties tot één
zoekresultaat. U kunt dit doen met behulp van het sleutelwoord "join" om op te geven welke objecten
om lid te worden en het "aan" -woord te gebruiken om de overeenkomende relatie tussen te specificeren
de twee objecten.

Gerelateerde lijst initialiseren:

 Lijst ListOfCars = nieuwe lijst() new Car name = "Mitsubishi", owner = "Jeff", model = 2005, new Car name = "Land Rover", owner = "Danny", model = 2001, new Car name = " Subaru ", owner =" Smith ", model = 2003, new Car name =" Toyota ", owner =" Alex ", model = 1992, new Car name =" BMW ", owner =" Danny ", model = 2006,; Lijst ListOfCarOwners = nieuwe lijst() nieuwe CarOwner owner_name = "Danny", leeftijd = 22, nieuwe CarOwner owner_name = "Jeff", age = 35, nieuwe CarOwner owner_name = "Smith", age = 19, new CarOwner owner_name = "Alex", leeftijd = 40;

Query:

 var QueryResult = uit auto in ListOfCars join carowner in ListOfCarOwners op car.owner is gelijk aan carowner.owner_name selecteer nieuw name = car.name, owner = car.owner, owner_age = carowner.age;

In de bovenstaande code hebben we een anoniem type gebruikt
de twee objecten in een enkel queryresultaat.

Objecthiërarchieën met groepsjoins

Tot nu toe hebben we geleerd hoe we LINQ kunnen gebruiken om een ​​flat te bouwen
lijst query resultaat. Met LINQ is het ook mogelijk om een ​​hiërarchische query te bereiken
resultaat met "GroupJoin". In eenvoudige bewoordingen kunnen we objecten toewijzen
eigenschappen van elk item met LINQ-query.

 Lijst ListOfCars = nieuwe lijst() new Car name = "Mitsubishi", owner = "Jeff", model = 2005, new Car name = "Land Rover", owner = "Danny", model = 2001, new Car name = " Subaru ", owner =" Smith ", model = 2003, new Car name =" Toyota ", owner =" Alex ", model = 1992, new Car name =" BMW ", owner =" Danny ", model = 2006,; Lijst ListOfCarOwners = nieuwe lijst() nieuwe CarOwner owner_name = "Danny", leeftijd = 22, nieuwe CarOwner owner_name = "Jeff", age = 35, nieuwe CarOwner owner_name = "Smith", age = 19, new CarOwner owner_name = "Alex", leeftijd = 40; var QueryResult = van carowner in ListOfCarOwners join auto in ListOfCars op carowner.owner_name is gelijk aan car.owner in carsGroup selecteer nieuw name = carowner.owner_name, cars = carsGroup; foreach (var carOwner in QueryResult) foreach (var car in carOwner.cars) Console.WriteLine ("Eigenaarnaam: 0, naam van de auto: 1, automodel: 2", carOwner.name, car.name , auto model);

In het bovenstaande voorbeeld wordt de clausule "Join" gevolgd door een "into"
een deel. Dit verschilt van de vorige join-bewerking die we hebben bekeken. Hier, de "into"
clausule wordt gebruikt om auto's te groeperen door de eigenaar (in carsGroup) en de groepering toe te wijzen aan de
"auto's" eigendom van het anonieme type.

Standaardqueryoperators

Tot nu toe is alles wat we hebben gezien ondersteund door de C # 3.0
syntaxis. Er is echter nog steeds een groot aantal bewerkingen die C # 3.0 niet doet
ondersteuning. De standaardqueryoperators bieden query-mogelijkheden, waaronder
filteren, projecteren, aggregeren, sorteren en meer. Deze bewerkingen worden daarom ondersteund
als methoden van de LINQ-bibliotheek en kan worden uitgevoerd op het resultaat van een query zoals getoond in de
volgende screenshot:

Deze operators staan ​​hieronder vermeld voor uw referentie.

Aggregate Operators

  • Som: geeft als resultaat de som van alle items
  • Max: retourneert het item met de maximale waarde
  • min: retourneert het item met de minimumwaarde
  • Gemiddelde: geeft de gemiddelde waarde voor de verzameling
  • Aggregaat: gebruikt voor het maken van een aangepaste aggregatie
  • LongCount: als het om een ​​grote verzameling gaat, retourneert deze methode een waarde tot de grootste waarde die door de klasse "lang" wordt ondersteund
  • tellen: geeft een "integer" terug voor het aantal items in de verzameling

Element Operators

  • Eerste: geeft als resultaat de eerste invoer uit de resultatenverzameling
  • FirstOrDefault: als lege verzameling de standaardwaarde retourneert, wordt anders het eerste item uit de verzameling geretourneerd
  • single: zal alleen elementen uit de verzameling retourneren
  • SingleOrDefault: als lege verzameling de standaardwaarde retourneert, retourneert anders alleen het element uit de verzameling
  • Laatste: geeft als resultaat de laatste invoer uit de verzameling
  • LastOrDefault: als lege verzameling de standaardwaarde retourneert, wordt anders het laatste gegeven uit de verzameling geretourneerd
  • ElementAt: geeft het element terug op de opgegeven positie
  • ElementAtOrDefault: als lege verzameling de standaardwaarde retourneert, wordt het element anders op de opgegeven positie geretourneerd

Stel verwante operators in

  • Behalve: vergelijkbaar met de link join in SQL, retourneert items uit de ene set die niet bestaat in een andere set
  • Unie: retourneert alle items van beide objecten
  • Snijden: geeft dezelfde elementen terug van beide sets
  • onderscheiden: retourneert unieke vermeldingen uit de verzameling

Generation Operators

  • DefaultIfEmpty: als het resultaat leeg is, wordt de standaardwaarde geretourneerd
  • Herhaling: herhaalt zich bij het retourneren van objecten voor een bepaald aantal keren
  • Leeg: zal een lege IEnumerable verzameling retourneren
  • reeks: retourneert een bereik van nummers voor een opgegeven startnummer en telt

Operators verfijnen

  • Waar: retourneert objecten die aan de opgegeven voorwaarde voldoen
  • OfType: retourneert objecten van het opgegeven type

Conversieoperators

  • Opkijken: geeft het resultaat als een opzoeking
  • ToList: geeft het resultaat als een lijstverzameling
  • ToDictionary: geeft het resultaat als een woordenboek
  • ToArray: geeft het resultaat als een matrixverzameling
  • AsQueryable: geeft het resultaat als een IQueryable
  • AsEnumerable: geeft het resultaat als IEnumerable
  • OfType: filtert de verzameling volgens het opgegeven type
  • Gegoten: gebruikt om een ​​zwak getypte collectie om te zetten in een sterk getypte collectie

Partitioning Operators

  • Nemen: geeft een gespecificeerd aantal records terug
  • takeWhile: retourneert een opgegeven aantal records terwijl de opgegeven voorwaarde evalueert naar waar
  • Overspringen: slaat opgegeven aantal invoeren over en geeft de rest terug
  • SkipWhile: slaat opgegeven aantal invoeren over terwijl de opgegeven voorwaarde evalueert naar waar

Quantifier Operators

  • Ieder: retourneert waar of onwaar voor een opgegeven voorwaarde
  • bevat: geeft true of false terug voor het bestaan ​​van het opgegeven object
  • Allemaal: retourneert waar of onwaar aan alle objecten die aan de opgegeven voorwaarde voldoen

Word lid van Operators

  • toetreden: retourneert items waarbij toetsen in sets hetzelfde zijn
  • GroupJoin: gebruikt om hiërarchische objecten te bouwen op basis van een hoofd- en detailrelatie

Gelijkheid Operatoren

  • SequenceEqual: geeft true als collecties gelijk zijn

Operatoren sorteren

  • Omgekeerde: geeft een omgekeerde verzameling terug
  • ThenBy: wordt gebruikt om verder te sorteren
  • ThenByDescending: wordt gebruikt om verder sorteren in aflopende volgorde uit te voeren
  • OrderBy: gebruikt om de volgorde te definiëren
  • OrderByDescending: wordt gebruikt om aflopende volgorde te definiëren

Projectieoperators

  • SelectMany: gebruikt om een ​​hiërarchische verzameling af te vlakken
  • kiezen: gebruikt om de eigenschappen te identificeren die moeten worden geretourneerd

Aaneenschakelingsoperatoren

  • concat: gebruikt om twee collecties samen te voegen

Dus wat nu?

LINQ heeft bewezen zeer nuttig te zijn voor het opvragen van objecten, en de SQL-achtige syntaxis maakt het gemakkelijk om te gebruiken
leren en gebruiken. Ook maakt het enorme aantal standaardoperators het mogelijk om een ​​aantal operatoren te ketenen
om complexe query's uit te voeren. In een vervolg op deze zelfstudie zullen we bekijken hoe LINQ kan worden gebruikt
query-databases en XML-inhoud ...

Verkoop .NET Scripts en componenten op CodeCanyon



  • Volg ons op Twitter of abonneer je op de Nettuts + RSS Feed voor de beste tutorials voor webontwikkeling op internet.