Query's in LINQ naar DataSet
Een query is een expressie waarmee gegevens uit een gegevensbron worden opgehaald. Query's worden meestal uitgedrukt in een gespecialiseerde querytaal, zoals SQL voor relationele databases en XQuery voor XML. Daarom moesten ontwikkelaars een nieuwe querytaal leren voor elk type gegevensbron of gegevensindeling waarop ze een query uitvoeren. Language-Integrated Query (LINQ) biedt een eenvoudigere consis tentmodus l voor het werken met gegevens in verschillende soorten gegevensbronnen en indelingen. In een LINQ-query werkt u altijd met programmeerobjecten.
Een LINQ-querybewerking bestaat uit drie acties: de gegevensbron of bronnen ophalen, de query maken en de query uitvoeren.
Gegevensbronnen die de IEnumerable<T> algemene interface implementeren, kunnen worden opgevraagd via LINQ. Het aanroepen van AsEnumerable een DataTable object retourneert een object dat de algemene IEnumerable<T> interface implementeert, die fungeert als de gegevensbron voor LINQ naar DataSet-query's.
In de query geeft u precies de informatie op die u uit de gegevensbron wilt ophalen. Een query kan ook opgeven hoe deze informatie moet worden gesorteerd, gegroepeerd en vormgegeven voordat deze wordt geretourneerd. In LINQ wordt een query opgeslagen in een variabele. Als de query is ontworpen om een reeks waarden te retourneren, moet de queryvariabele zelf een opsommingstype zijn. Deze queryvariabele voert geen actie uit en retourneert geen gegevens; alleen de querygegevens worden opgeslagen. Nadat u een query hebt gemaakt, moet u die query uitvoeren om gegevens op te halen.
In een query die een reeks waarden retourneert, bevat de queryvariabele zelf nooit de queryresultaten en worden alleen de queryopdrachten opgeslagen. De uitvoering van de query wordt uitgesteld totdat de queryvariabele wordt herhaald in een foreach
of For Each
lus. Dit wordt de uitgestelde uitvoering genoemd. Dat wil gezegd, de uitvoering van query's vindt enige tijd plaats nadat de query is gemaakt. Dit betekent dat u zo vaak als u wilt een query kunt uitvoeren. Dit is handig wanneer u bijvoorbeeld een database hebt die wordt bijgewerkt door andere toepassingen. In uw toepassing kunt u een query maken om de meest recente informatie op te halen en de query herhaaldelijk uit te voeren, waarbij de bijgewerkte gegevens telkens worden geretourneerd.
In tegenstelling tot uitgestelde query's, die een reeks waarden retourneren, worden query's die een singleton-waarde retourneren, onmiddellijk uitgevoerd. Enkele voorbeelden van singleton-query's zijn Count, Max, Averageen First. Deze worden onmiddellijk uitgevoerd omdat de queryresultaten vereist zijn om het singleton-resultaat te berekenen. Als u bijvoorbeeld het gemiddelde van de queryresultaten wilt vinden, moet de query worden uitgevoerd, zodat de gemiddelde functie invoergegevens bevat om mee te werken. U kunt ook de ToList of ToArray methoden voor een query gebruiken om onmiddellijke uitvoering van een query af te dwingen die geen singleton-waarde produceert. Deze technieken om onmiddellijke uitvoering af te dwingen, kunnen handig zijn wanneer u de resultaten van een query in de cache wilt opslaan.
Query's
LINQ naar DataSet-query's kan worden geformuleerd in twee verschillende syntaxis: syntaxis van query-expressie en op methode gebaseerde querysyntaxis.
Syntaxis van query-expressie
Queryexpressies zijn een declaratieve querysyntaxis. Met deze syntaxis kan een ontwikkelaar query's schrijven in C# of Visual Basic in een indeling die vergelijkbaar is met SQL. Met behulp van de syntaxis van query-expressies kunt u zelfs complexe filter-, volgorde- en groeperingsbewerkingen uitvoeren op gegevensbronnen met minimale code. Zie LINQ-queryexpressies en Basic Query Operations (Visual Basic) voor meer informatie.
De .NET Framework Common Language Runtime (CLR) kan de syntaxis van de queryexpressie zelf niet lezen. Daarom worden query-expressies tijdens het compileren vertaald naar iets dat de CLR begrijpt: methode-aanroepen. Deze methoden worden de standaardqueryoperators genoemd. Als ontwikkelaar hebt u de mogelijkheid om ze rechtstreeks aan te roepen met behulp van methodesyntaxis in plaats van querysyntaxis te gebruiken. Zie Querysyntaxis en methodesyntaxis in LINQ voor meer informatie. Zie Overzicht van Standard-queryoperators voor meer informatie over de standaardqueryoperators.
In het volgende voorbeeld worden Select alle rijen uit Product
de tabel geretourneerd en worden de productnamen weergegeven.
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> query =
from product in products.AsEnumerable()
select product;
Console.WriteLine("Product Names:");
foreach (DataRow p in query)
{
Console.WriteLine(p.Field<string>("Name"));
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = From product In products.AsEnumerable() _
Select product
Console.WriteLine("Product Names:")
For Each p In query
Console.WriteLine(p.Field(Of String)("Name"))
Next
Querysyntaxis op basis van methode
De andere manier om LINQ te formuleren op DataSet-query's is door op methoden gebaseerde query's te gebruiken. De querysyntaxis op basis van een methode is een reeks directe methode-aanroepen naar LINQ-operatormethoden, waarbij lambda-expressies als parameters worden doorgegeven. Zie Lambda-expressies voor meer informatie.
In dit voorbeeld worden Select alle rijen uit Product
geretourneerd en worden de productnamen weergegeven.
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
var query = products.AsEnumerable().
Select(product => new
{
ProductName = product.Field<string>("Name"),
ProductNumber = product.Field<string>("ProductNumber"),
Price = product.Field<decimal>("ListPrice")
});
Console.WriteLine("Product Info:");
foreach (var productInfo in query)
{
Console.WriteLine("Product name: {0} Product number: {1} List price: ${2} ",
productInfo.ProductName, productInfo.ProductNumber, productInfo.Price);
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = products.AsEnumerable() _
.Select(Function(product As DataRow) New With _
{ _
.ProductName = product.Field(Of String)("Name"), _
.ProductNumber = product.Field(Of String)("ProductNumber"), _
.Price = product.Field(Of Decimal)("ListPrice") _
})
Console.WriteLine("Product Info:")
For Each product In query
Console.Write("Product name: " & product.ProductName)
Console.Write("Product number: " & product.ProductNumber)
Console.WriteLine("List price: $ " & product.Price)
Next
Query's opstellen
Zoals eerder in dit onderwerp is vermeld, slaat de queryvariabele zelf alleen de queryopdrachten op wanneer de query is ontworpen om een reeks waarden te retourneren. Als de query geen methode bevat die onmiddellijk wordt uitgevoerd, wordt de werkelijke uitvoering van de query uitgesteld totdat u de queryvariabele in een foreach
of For Each
lus doorloopt. Door de uitgestelde uitvoering kunnen meerdere query's worden gecombineerd of een query worden uitgebreid. Wanneer een query wordt uitgebreid, wordt deze aangepast om de nieuwe bewerkingen op te nemen. De uiteindelijke uitvoering geeft de wijzigingen weer. In het volgende voorbeeld retourneert de eerste query alle producten. De tweede query breidt de eerste uit door Where
alle producten van grootte L te retourneren:
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> productsQuery =
from product in products.AsEnumerable()
select product;
IEnumerable<DataRow> largeProducts =
productsQuery.Where(p => p.Field<string>("Size") == "L");
Console.WriteLine("Products of size 'L':");
foreach (DataRow product in largeProducts)
{
Console.WriteLine(product.Field<string>("Name"));
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim productsQuery = From product In products.AsEnumerable() _
Select product
Dim largeProducts = _
productsQuery.Where(Function(p) p.Field(Of String)("Size") = "L")
Console.WriteLine("Products of size 'L':")
For Each product In largeProducts
Console.WriteLine(product.Field(Of String)("Name"))
Next
Nadat een query is uitgevoerd, kunnen er geen extra query's worden samengesteld, en alle volgende query's gebruiken de LINQ-operators in het geheugen. De uitvoering van query's vindt plaats wanneer u de queryvariabele in een foreach
of-instructie For Each
of door een aanroep naar een van de LINQ-conversieoperators die onmiddellijke uitvoering veroorzaken, door te voeren. Deze operators omvatten het volgende: ToList, ToArray, ToLookupen ToDictionary.
In het volgende voorbeeld retourneert de eerste query alle producten die zijn besteld op catalogusprijs. De ToArray methode wordt gebruikt om onmiddellijke uitvoering van query's af te dwingen:
// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);
DataTable products = ds.Tables["Product"];
IEnumerable<DataRow> query =
from product in products.AsEnumerable()
orderby product.Field<Decimal>("ListPrice") descending
select product;
// Force immediate execution of the query.
IEnumerable<DataRow> productsArray = query.ToArray();
Console.WriteLine("Every price from highest to lowest:");
foreach (DataRow prod in productsArray)
{
Console.WriteLine(prod.Field<Decimal>("ListPrice"));
}
' Fill the DataSet.
Dim ds As New DataSet()
ds.Locale = CultureInfo.InvariantCulture
' See the FillDataSet method in the Loading Data Into a DataSet topic.
FillDataSet(ds)
Dim products As DataTable = ds.Tables("Product")
Dim query = _
From product In products.AsEnumerable() _
Order By product.Field(Of Decimal)("ListPrice") Descending _
Select product
' Force immediate execution of the query.
Dim productsArray = query.ToArray()
Console.WriteLine("Every price From highest to lowest:")
For Each prod In productsArray
Console.WriteLine(prod.Field(Of Decimal)("ListPrice"))
Next