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.
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.
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:
LijstListOfCars = 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:
IEnumerableQueryResult = 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
"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.
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:
IEnumerableQueryResult = uit auto in ListOfCars selecteer nieuwe CarOwner owner_name = car.owner;
In de voorgaande code wordt het type queryresultaat als gedeclareerd
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.
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.
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.
IEnumerableQueryResult = 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.
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.
IEnumerableQueryResult = 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:
IEnumerableQueryResult = uit auto in ListOfCars orderby car.model aflopende geselecteerde auto;
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.
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:
LijstListOfCars = 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.
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.
LijstListOfCars = 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.
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.
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 ...