LINQ
LINQ (Abkürzung für Language Integrated Query; Aussprache Link) ist ein programmtechnisches Verfahren von Microsoft zum Zugriff auf Daten. LINQ wurde federführend von Erik Meijer entwickelt<ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft Research ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden.).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref> und erschien erstmals mit .NET Framework 3.5.
Ziel von LINQ[Bearbeiten]
Die Daten, auf die ein Programm zugreift, stammen aus unterschiedlichen Quellen.<ref name="PialorsiS115">Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.</ref> Dazu gehören<ref>Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.</ref>
- interne Quellen wie Felder sowie Objekt-Listen und -Hierarchien;
- externe Quellen wie XML-Dokumente, Datenbanktabellen, Textdateien, Excel-Dateien, E-Mail-Nachrichten, SharePoint-Listen und viele andere.
Jede dieser Datenquellen hat ihre eigenen Zugriffsmethoden. Dies führt dazu, dass sich der Programmierer in jedem Einzelfall mit den Details der jeweiligen Methode beschäftigen muss. Ferner muss jedes Mal das Programm geändert werden, wenn Daten aus einer Quelle in eine Quelle eines anderen Typs verschoben werden.
LINQ versucht dieses Problem zu beseitigen, indem es innerhalb des .Net-Frameworks eine einheitliche Methode für jeglichen Datenzugriff zur Verfügung stellt. Die Syntax der Abfragen in LINQ ist ähnlich der von SQL. Im Unterschied zu SQL stellt LINQ jedoch auch Sprachelemente zur Verfügung, die zum Zugriff auf hierarchische und Netzwerk-Strukturen geeignet sind, indem sie die dort vorhandenen Beziehungen ausnutzen.<ref>Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.</ref>
Arbeitsweise[Bearbeiten]
LINQ ist eine Sammlung von Erweiterungsmethoden, die auf Monaden operieren.<ref>Brian Beckman: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden.).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref><ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft, Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden.).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref> Zudem gibt es in einigen .NET-Sprachen wie C#, VB.NET und F# eigene Schlüsselwörter für eine vorbestimmte Menge an LINQ-Methoden.<ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft ehemals im Vorlage:Referrer (nicht mehr online verfügbar)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref><ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden.).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref> Monaden werden in .NET als generische Klassen oder Interfaces mit einzelnem Typargument (z. B. <syntaxhighlight lang="csharp" inline>IEnumerable<T></syntaxhighlight>, <syntaxhighlight lang="csharp" inline>IObservable<T></syntaxhighlight>) abgebildet.
LINQ-Anweisungen sind unmittelbar als Quelltext in .NET-Programme eingebettet.<ref>Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.</ref> Somit kann der Code durch den Compiler auf Fehler geprüft werden. Andere Verfahren wie ADO und ODBC hingegen verwenden Abfragestrings. Diese können erst zur Laufzeit interpretiert werden; dann wirken Fehler gravierender und sind schwieriger zu analysieren.
Innerhalb des Quellprogramms in C# oder VB.NET präsentiert LINQ die Abfrage-Ergebnisse als streng typisierte Aufzählungen.<ref>Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.</ref> Somit gewährleistet es Typsicherheit bereits zur Übersetzungszeit.
Sogenannte LINQ-Anbieter<ref name="PialorsiS115" /> (englisch Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) übersetzen die LINQ-Anweisungen in die speziellen Zugriffsmethoden der jeweiligen Datenquelle. Innerhalb der .NET-Plattform stehen unter anderem folgende Anbieter zur Verfügung:<ref>Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.</ref>
- LINQ to Objects zum Zugriff auf Objektlisten und -Hierarchien im Arbeitsspeicher
- LINQ to SQL zur Abfrage und Bearbeitung von Daten in MS-SQL-Datenbanken
- LINQ to Entities zur Abfrage und Bearbeitung von Daten im relationalen Modell von ADO.NET;<ref>Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.</ref>
- LINQ to XML zum Zugriff auf XML-Inhalte
- LINQ to DataSet zum Zugriff auf ADO.NET-Datensammlungen und -Tabellen
- LINQ to SharePoint zum Zugriff auf SharePoint-Daten.<ref>Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.</ref>
Wichtige Konzepte[Bearbeiten]
Die Beispiele sind, sofern nicht anders angegeben, in C#.
Verzögerte Auswertung[Bearbeiten]
LINQ-Ausdrücke werden nicht bei ihrer Definition ausgeführt, sondern wenn der Wert abgefragt wird. Dies wird als Lazy Evaluation (auch Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) bezeichnet. Dadurch kann die Abfrage auch mehrfach verwendet werden.
<syntaxhighlight lang="csharp"> var numbers = new List<int>() {1,2,3,4}; // list with 4 numbers
// query is defined but not evaluated var query = from x in numbers
select x;
numbers.Add(5); // add a 5th number
// now the query gets evaluated Console.WriteLine(query.Count()); // 5
numbers.Add(6); // add a 6th number
Console.WriteLine(query.Count()); // 6 </syntaxhighlight>
Die verzögerte Auswertung kann auf verschiedene Weisen implementiert werden. Beispielsweise verwendet LINQ to Objects Delegates, während LINQ to SQL stattdessen das <syntaxhighlight lang="csharp" inline>IQueryable<T></syntaxhighlight>-Interface implementiert. Um die Veränderung des Ergebnisses der Abfrage zu verhindern, muss diese in einen anderen Typ konvertiert (englisch: Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) werden. Hierzu dienen Konvertierungsmethoden wie <syntaxhighlight lang="csharp" inline>AsEnumerable()</syntaxhighlight>, <syntaxhighlight lang="csharp" inline>ToArray()</syntaxhighlight>, <syntaxhighlight lang="csharp" inline>ToList()</syntaxhighlight>, <syntaxhighlight lang="csharp" inline>ToDictionary()</syntaxhighlight>, <syntaxhighlight lang="csharp" inline>ToLookup()</syntaxhighlight> usw.
Falls die LINQ-Abfrage eine Funktion aufruft, die eine Ausnahmebehandlung erfordert, so muss der Try-Catch-Block die Verwendung der Abfrage umklammern und nicht deren Erstellung.
Auflösung von Erweiterungsmethoden[Bearbeiten]
LINQ-Funktionen werden als Erweiterungsmethoden (englisch: Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) implementiert. Gegeben sei eine Aufzählung von Elementen eines Typs:
Über eine Erweiterungsmethode kann nun etwa die <syntaxhighlight lang="csharp" inline>Where()</syntaxhighlight>-Methode zur Filterung nach beliebigen Kriterien (re-)implementiert werden:
<syntaxhighlight lang="csharp"> public static class EnumerableExtensions {
public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
foreach (var element in source)
{
if (predicate(element)) yield return element;
}
}
} </syntaxhighlight>
Bestimmte .NET-Sprachen besitzen eigene Schlüsselwörter, um die Methoden aufzurufen:
<syntaxhighlight lang="csharp"> var query =
from e in employees where e.DepartmentId == 5 select e;
</syntaxhighlight>
Diese Schlüsselwörter werden vom Compiler in die entsprechenden Methodenaufrufe aufgelöst:
<syntaxhighlight lang="csharp"> var query = employees.Where(e => e.DepartmentId == 5).Select(e => e); </syntaxhighlight>
Da es sich um Erweiterungsmethoden handelt, muss der Compiler die Methodenaufrufe in einen Aufruf der Methoden der passenden Erweiterungsklasse auflösen:
<syntaxhighlight lang="csharp"> var query = Enumerable.Select(EnumerableExtensions.Where(employees, e => e.DepartmentId == 5), e => e); </syntaxhighlight>
Wichtige Operatoren[Bearbeiten]
From[Bearbeiten]
From definiert die Datenquelle einer Abfrage (Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) oder Unterabfrage (Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.), sowie eine Bereichsvariable (Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) die ein einzelnes Element der Datenquelle (Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) repräsentiert. <syntaxhighlight lang="csharp"> from rangeVariable in dataSource // ... </syntaxhighlight>
Abfragen können mehrere from-Operationen besitzen, um Joins von mehreren Datenquellen zu ermöglichen. Hierbei gilt zu beachten, dass die Join-Bedingung bei mehreren from-Operationen durch die Datenstruktur definiert wird und sich vom Konzept eines Joins in Relationalen Datenbanken unterscheidet.
<syntaxhighlight lang="csharp"> var queryResults =
from c in customers
from o in orders
select new { c.Name, o.OrderId, o.Price };
</syntaxhighlight>
oder kürzer:
<syntaxhighlight lang="csharp"> var queryResults =
from c in customers, o in orders
select new { c.Name, o.OrderId, o.Price };
</syntaxhighlight>
Where[Bearbeiten]
Where definiert einen Filter auf den auszuwählenden Daten.
<syntaxhighlight lang="csharp"> var queryResults =
from c in customers
from o in orders
where o.Date > DateTime.Now - TimeSpan.FromDays(7)
select new { c.Name, o.OrderId, o.Price };
</syntaxhighlight>
Select[Bearbeiten]
Select definiert eine Projektion bzw. die Form des Ergebnisses der LINQ-Abfrage.
Häufig wird eine Teilmenge von Eigenschaften projiziert, wobei dafür anonyme Klassen verwendet werden (d. h. new { …, … }) bzw. ab C# 7.0 auch Wertetupel ((…, …)).
Group[Bearbeiten]
Group wird verwendet, um Elemente nach einem bestimmten Schlüssel zu gruppieren:
<syntaxhighlight lang="csharp"> var groupedEmployees =
from e in Employees group e by e.Department; // group by department
</syntaxhighlight>
Als Schlüssel kann auch ein anonymer Typ verwendet werden, der sich aus mehreren Schlüsseln zusammensetzt:
<syntaxhighlight lang="csharp"> var groupedEmployees =
from e in Employees
group e by new { e.Department , e.Age }; // group by department and age
</syntaxhighlight>
Into[Bearbeiten]
Into kann verwendet werden um das Ergebnis einer select, group oder join-Operation in einer temporären Variable zu speichern.
<syntaxhighlight lang="csharp"> var groupedEmployees =
from e in Employees
group e by e.Department into EmployeesByDepartment
select new { Department = EmployeesByDepartment.Key, EmployeesByDepartment.Count() };
</syntaxhighlight>
OrderBy und ThenBy[Bearbeiten]
OrderBy und ThenBy wird verwendet, um eine Liste von Elementen in aufsteigender Reihenfolge zu sortieren.
<syntaxhighlight lang="csharp"> var groupedEmployees =
from e in Employees orderby e.Age // order employees by age; youngest first thenby e.Name // order same-age employees by name; sort A-to-Z select e;
</syntaxhighlight>
Mit Hilfe von OrderByDescending und ThenByDescending wird die Liste in absteigender Reihenfolge sortiert:
<syntaxhighlight lang="csharp"> var groupedEmployees =
from e in Employees orderby e.Age descending // oldest first thenby e.Name descending // sort Z-to-A select e;
</syntaxhighlight>
Reverse[Bearbeiten]
Reverse kehrt die Reihenfolge der Elemente um.
Join[Bearbeiten]
Join ermöglicht Inner Joins, Group Joins und Left Outer Joins.
- Inner Join
- Ein Inner Join bildet die äußere Datenquelle auf die innere Datenquelle ab und liefert ein „flaches“ Ergebnis zurück. Elemente der äußeren Datenquelle, zu denen kein passendes Element der inneren Datenquelle existiert, werden verworfen.
<syntaxhighlight lang="csharp"> var productCategories =
from c in categories // outer datasource
join p in products // inner datasource
on c.CategoryId equals p.CategoryId // categories without products are ignored
select new { c.CategoryName, p.ProductName };
</syntaxhighlight>
- Group Join
- Ein Group Join erzeugt eine hierarchische Ergebnismenge. Hierbei werden die Elemente der inneren Datenquelle mit den entsprechenden Elementen der äußeren Datenquelle gruppiert. Elemente zu denen kein entsprechendes Element der äußeren Datenquelle existiert, werden mit einem leeren Array verbunden.
<syntaxhighlight lang="csharp"> var productCategories =
from c in categories
join p in products
on c.CategoryId equals p.CategoryId
into productsInCategory
select new { c.CategoryName, Products = productsInCategory };
</syntaxhighlight>
- Ein Group Join ist in SQL nicht abbildbar, da SQL keine hierarchische Ergebnismenge zulässt. VB.NET besitzt mit Group Join ein eigenes Schlüsselwort.
- Left Outer Join
- Ein Left Outer Join bildet die äußere Datenquelle auf die innere Datenquelle ab und liefert ein „flaches“ Ergebnis zurück. Elemente der äußeren Datenquelle, zu denen kein passendes Element der inneren Datenquelle existiert, werden mit einem Standardwert versehen. Um den Standardwert zu definieren, wird die <syntaxhighlight lang="csharp" inline>DefaultIfEmpty()</syntaxhighlight>-Erweiterungsmethode verwendet, die leere Aufzählungen in eine einelementige Aufzählung mit einem Standardwert wandelt:
<syntaxhighlight lang="csharp"> var productCategories =
from c in categories
join p in products
on c.CategoryId equals p.CategoryId
into productsInCategory
from pic in productsInCategory.DefaultIfEmpty(
new Product(CategoryId = 0, ProductId = 0, ProductName = String.Empty))
select new { c.CategoryName, p.ProductName };
</syntaxhighlight>
Let[Bearbeiten]
Let ermöglicht es das Ergebnis einer Teilabfrage in einer Variable zu speichern, um diese später in der Abfrage verwenden zu können.
<syntaxhighlight lang="csharp"> var ordersByProducts =
from c in categories
join p in products
on c.CategoryId equals p.CategoryId
into productsByCategory
let ProductCount = productsByCategory.Count()
orderby ProductCount
select new { c.CategoryName, ProductCount };
</syntaxhighlight>
Any[Bearbeiten]
Any wird verwendet, um festzustellen, ob eine Sequenz leer ist oder ein bestimmtes Prädikat enthält. <syntaxhighlight lang="csharp"> bool containsAnyElements = Enumerable.Empty<int>().Any(); // false bool containsSix = Enumerable.Range(1,10).Any(x => x == 6); // true </syntaxhighlight>
Contains[Bearbeiten]
Contains wird verwendet, um festzustellen, ob ein bestimmter Wert in einer Sequenz enthalten ist. <syntaxhighlight lang="csharp"> bool containsSix = Enumerable.Range(1,10).Contains(6); // true </syntaxhighlight>
Skip und Take[Bearbeiten]
Skip wird verwendet, um eine bestimmte Anzahl von Elementen einer Sequenz zu überspringen. Take wird verwendet, um eine maximale Anzahl von Elementen einer Sequenz auszuwählen.
<syntaxhighlight lang="csharp"> IEnumerable<int> Numbers = Enumerable.Range(1,10).Skip(2).Take(5); // {3,4,5,6,7} </syntaxhighlight>
Zusätzlich sind die Erweiterungsmethoden <syntaxhighlight lang="csharp" inline>SkipWhile()</syntaxhighlight> und <syntaxhighlight lang="csharp" inline>TakeWhile()</syntaxhighlight> definiert, für die in VB.NET eigene Schlüsselwörter definiert sind. Diese Methoden erlauben die Verwendung eines Prädikats, welches definiert welche Elemente übersprungen bzw. ausgewählt werden.
Distinct[Bearbeiten]
Distinct wird verwendet, um eindeutige Elemente einer Sequenz auszuwählen. <syntaxhighlight lang="csharp"> IEnumerable<int> MultipleNumbers = new List<int>() {0,1,2,3,2,1,4}; IEnumerable<int> DistinctNumbers = MultipleNumbers.Distinct(); // {0,1,2,3,4} </syntaxhighlight>
Union, Intersect und Except[Bearbeiten]
Für eine Liste von Elementen können die Mengenoperatoren Union, Intersect und Except eingesetzt werden: <syntaxhighlight lang="csharp"> var NumberSet1 = {1,5,6,9}; var NumberSet2 = {4,5,7,11};
var union = NumberSet1.Union(NumberSet2); // 1,5,6,9,4,7,11 var intersect = NumberSet1.Intersect(NumberSet2); // 5 var except = NumberSet1.Except (NumberSet2); // 1,6,9 </syntaxhighlight>
Aggregate[Bearbeiten]
Aggregate wird verwendet, um eine Aggregat-Funktion auf eine Datenquelle anzuwenden.
<syntaxhighlight lang="csharp"> var nums = new[]{1,2,3,4,5}; var sum = nums.Aggregate( (a,b) => a + b); // sum = 1+2+3+4+5 = 15 </syntaxhighlight>
Zudem sind wichtige Aggregat-Funktionen vordefiniert. Vordefinierte Aggregat-Funktionen sind etwa <syntaxhighlight lang="csharp" inline>Count()</syntaxhighlight>, <syntaxhighlight lang="csharp" inline>LongCount()</syntaxhighlight>, <syntaxhighlight lang="csharp" inline>Sum()</syntaxhighlight>, <syntaxhighlight lang="csharp" inline>Min()</syntaxhighlight>, <syntaxhighlight lang="csharp" inline>Max()</syntaxhighlight> und <syntaxhighlight lang="csharp" inline>Average()</syntaxhighlight>.
Zip[Bearbeiten]
Zip kombiniert zwei Sequenzen miteinander, bis eine Sequenz zu Ende ist. <syntaxhighlight lang="csharp" line="1"> IEnumerable<string> Days = new List<string>() { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; IEnumerable<int> Numbers = Enumerable.Range(1,10); // {1,2,3,4,5,6,7,8,9,10} // Numbers 8..10 will be ignored IEnumerable<string> NumberedDays = Days.Zip(Numbers, (day, number) => String.Format("{0}:{1}", number, day) ); // {"1:Monday", "2:Tuesday", ..., "7:Sunday"} </syntaxhighlight>
Concat[Bearbeiten]
Concat hängt an eine Sequenz eine weitere Sequenz gleichen Typs.
SequenceEqual[Bearbeiten]
SequenceEqual prüft, ob zwei Sequenzen die gleiche Länge aufweisen und ob die Elemente an der jeweiligen Position der entsprechenden Sequenzen gleich sind. Zum Vergleich wird entweder das <syntaxhighlight lang="csharp" inline>IEqualityComparer<T></syntaxhighlight> Interface, die <syntaxhighlight lang="csharp" inline>Equals()</syntaxhighlight>-Methode von <syntaxhighlight lang="csharp" inline>TSource</syntaxhighlight> oder die <syntaxhighlight lang="csharp" inline>GetHashCode()</syntaxhighlight>-Methode abgefragt.
SelectMany[Bearbeiten]
SelectMany<ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft ehemals im Vorlage:Referrer (nicht mehr online verfügbar)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref> wird im Wesentlichen dazu eingesetzt, eine Hierarchie abzuflachen. SelectMany funktioniert hierbei wie der Bind-Operator <syntaxhighlight lang="haskell" inline>>>=</syntaxhighlight>, auch Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden. (Schaufel) genannt, in Haskell. <syntaxhighlight lang="csharp"> class Book {
public string Title { get; set; }
public List<Author> Authors { get; set; }
} class Author {
public string Name { get; set; }
} class Foo {
public IEnumerable<string> GetAuthorsFromBooks(IEnumerable<Book> books)
{
// Input-Monad: Enumerable Book Author
// Output-Monad: Enumerable Author
return books.SelectMany( book => book.Authors);
}
} </syntaxhighlight>
Ein typischer Anwendungsfall für die Abflachung einer Hierarchie ist es, alle Dateien in einem Verzeichnis sowie den Unterverzeichnissen des Verzeichnisses aufzulisten. <syntaxhighlight lang="csharp"> IEnumerable<string> GetFilesInSubdirectories(string rootDirectory) {
var directoryInfo = new DirectoryInfo(rootDirectory); // get the root directory
return directoryInfo.GetDirectories() // get directories in the root directory
.SelectMany(dir => GetFilesInSubdirectories(dir.FullName)) // recursively flattening the hierarchy of directories
.Concat(directoryInfo.GetFiles().Select(file => file.FullName)); // get the file name for each file in the directories
} </syntaxhighlight>
Skalar-Selektoren[Bearbeiten]
LINQ definiert verschiedene Selektoren für skalare Ergebnisse:
| Methode | Ergebnis |
|---|---|
ElementAt(n) |
Gibt das n-te Element zurück, falls die Anfrage ein oder mehrere Ergebnisse liefert. Wirft eine Exception, falls weniger als n Ergebnisse zurückgeliefert werden. |
ElementAtOrDefault(n) |
Gibt das n-te Element zurück, falls die Anfrage ein oder mehrere Ergebnisse liefert. Gibt den Standardwert zurück, falls weniger als n Ergebnisse zurückgeliefert werden. |
First() |
Gibt das erste Element zurück, falls die Anfrage ein oder mehrere Ergebnisse liefert. Wirft eine Exception, falls keine Ergebnisse zurückgeliefert werden. |
FirstOrDefault() |
Gibt das erste Element zurück, falls die Anfrage ein oder mehrere Ergebnisse liefert. Gibt den Standardwert zurück, falls keine Ergebnisse zurückgeliefert werden. |
Last() |
Gibt das letzte Element zurück, falls die Anfrage ein oder mehrere Ergebnisse liefert. Wirft eine Exception, falls keine Ergebnisse zurückgeliefert werden. |
LastOrDefault() |
Gibt das letzte Element zurück, falls die Anfrage ein oder mehrere Ergebnisse liefert. Gibt den Standardwert zurück, falls keine Ergebnisse zurückgeliefert werden. |
Single() |
Gibt das eine Element zurück, welches die Anfrage liefert. Wirft eine Exception, falls keine oder mehrere Ergebnisse zurückgeliefert werden. |
SingleOrDefault() |
Gibt das eine Element zurück, welches die Anfrage liefert. Gibt den Standardwert zurück, falls keine Ergebnisse geliefert werden. Wirft eine Exception, falls mehrere Ergebnisse zurückgeliefert werden. |
Erweitern von LINQ[Bearbeiten]
Definition eigener Monaden[Bearbeiten]
LINQ kann auf beliebige Monaden angewendet werden. Monaden sind hierbei Adapter (englisch: Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) für einen bestimmten Typ. Vordefinierte Monaden sind z. B. <syntaxhighlight lang="csharp" inline>IEnumerable<T></syntaxhighlight>, <syntaxhighlight lang="csharp" inline>IList<T></syntaxhighlight>, <syntaxhighlight lang="csharp" inline>Nullable<T></syntaxhighlight> und <syntaxhighlight lang="csharp" inline>Task<T></syntaxhighlight>.
Jedoch können auch eigene Monaden wie z. B. <syntaxhighlight lang="csharp" inline>IRepository<T></syntaxhighlight> oder <syntaxhighlight lang="csharp" inline>IHandler<T></syntaxhighlight> erstellt werden, um die Funktionalität von LINQ zu erweitern. Hierfür müssen passende Erweiterungsmethoden definiert werden. Die Verwendung von Monaden dient hierbei dazu die Menge an Boilerplate-Code zu reduzieren.
Identität[Bearbeiten]
Die einfachste Monade ist die Identität, welche in .NET üblicherweise als <syntaxhighlight lang="csharp" inline>Identity<T></syntaxhighlight> bezeichnet wird: <syntaxhighlight lang="csharp"> public class Identity<T> {
public T Value { get; private set; }
public Identity(T value)
{
Value = value;
}
} </syntaxhighlight> Für diese Klasse lassen sich nun die folgenden Erweiterungsmethoden erstellen: <syntaxhighlight lang="csharp"> // Unit-Methode // Konvertiert einen beliebigen Wert in eine Identität public static Identity<T> ToIdentity<T>(this T value) {
return new Identity<T>(value);
}
// Bind-Methode // Verknüpft Funktionen die eine Identität zurückgeben public static Identity Bind<A, B>(this Identity<A> m, Func<A, Identity> f) {
return f(m.Value);
} </syntaxhighlight> Diese Monade kann nun als Lambda-Ausdruck (als Skriptfehler: Ein solches Modul „Vorlage:lang“ ist nicht vorhanden.) verwendet werden: <syntaxhighlight lang="csharp"> var hello = "Hello".ToIdentity().Bind(h => "Monad".ToIdentity().Bind( m => String.Format("{0} {1}!", h, m) ));
Console.WriteLine(hello.Value); // "Hello Monad!" </syntaxhighlight> Um die Monade in LINQ verwenden zu können, muss eine <syntaxhighlight lang="csharp" inline>SelectMany()</syntaxhighlight>-Erweiterungsmethode implementiert werden. Diese ist lediglich ein Alias für <syntaxhighlight lang="csharp" inline>Bind()</syntaxhighlight>. Es besteht daher die Möglichkeit
- die <syntaxhighlight lang="csharp" inline>Bind()</syntaxhighlight>-Methode umzubenennen bzw. zu kapseln
- die <syntaxhighlight lang="csharp" inline>Bind()</syntaxhighlight>-Methode mit Funktionskomposition zu erstellen und umzubenennen bzw. zu kapseln
- beides:
<syntaxhighlight lang="csharp"> // SelectMany = Bind public static Identity SelectMany<A, B>(this Identity<A> m, Func<A, Identity> f) {
return Bind(m, f); // alternativ mit aufgelöstem Bind(): // return f(m.Value);
}
// Bind mit Funktionskomposition public static Identity<C> SelectMany<A, B, C>(this Identity<A> m, Func<A, Identity> f, Func<A, B, C> select) {
return select(m.Value, m.Bind(f).Value).ToIdentity();
// alternativ mit aufgelöstem Bind(): // return select(m.Value, f(m.Value).Value).ToIdentity();
} </syntaxhighlight> Die Monade kann nun mit Hilfe von LINQ-Schlüsselwörtern verarbeitet werden: <syntaxhighlight lang="csharp"> var hello = from h in "Hello".ToIdentity()
from m in "Monad".ToIdentity()
select String.Format("{0} {1}!", h, m);
Console.WriteLine(hello.Value); // "Hello Monad!" </syntaxhighlight>
Maybe[Bearbeiten]
Eine weitere einfache Monade ist <syntaxhighlight lang="csharp" inline>Maybe<T></syntaxhighlight>, welche ähnlich funktioniert wie die <syntaxhighlight lang="csharp" inline>Nullable<T></syntaxhighlight>-Struktur<ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft ehemals im Vorlage:Referrer (nicht mehr online verfügbar)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref><ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft ehemals im Vorlage:Referrer (nicht mehr online verfügbar)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref>. Die Maybe-Monade lässt sich hierbei auf verschiedene Arten implementieren:
- Variante 1
- HasValue-Eigenschaft bestimmt ob Maybe Nothing (d. h. leer) ist.
Definition der Monade: <syntaxhighlight lang="csharp"> class Maybe<T> {
public readonly static Maybe<T> Nothing = new Maybe<T>();
public T Value { get; private set; }
public bool HasValue { get; private set; }
Maybe()
{
HasValue = false;
}
public Maybe(T value)
{
Value = value;
HasValue = true;
}
public override string ToString()
{
return (HasValue) ? Value.ToString() : String.Empty;
}
} </syntaxhighlight> Definition der Unit-Methode: <syntaxhighlight lang="csharp"> public static Maybe<T> ToMaybe<T>(this T value) {
return new Maybe<T>(value);
} </syntaxhighlight> Definition der Bind-Methode: <syntaxhighlight lang="csharp"> private static Maybe Bind<T, U>(this Maybe<T> m, Func<T, Maybe> f) {
return (m.HasValue) ? f(m.Value) : Maybe.Nothing;
}
public static Maybe SelectMany<T, U>(this Maybe<T> m, Func<T, Maybe> f) {
return Bind<T, U>(m, f);
}
public static Maybe<C> SelectMany<A, B, C>(this Maybe<A> m, Func<A, Maybe> f, Func<A, B, C> select) {
return m.Bind(x => f(x).Bind(y => select(x,y).ToMaybe()));
} </syntaxhighlight> Verwendung: <syntaxhighlight lang="csharp"> // null-propagation of nullables var r = from x in 5.ToMaybe()
from y in Maybe<int>.Nothing
select x + y;
Console.WriteLine(r.Value); // String.Empty </syntaxhighlight>
- Variante 2
- konkreter Typ bestimmt ob Nothing oder Something
Definition der Monade: <syntaxhighlight lang="csharp"> public interface Maybe<T>{}
public class Nothing<T> : Maybe<T> {
public override string ToString()
{
return String.Empty;
}
}
public class Something<T> : Maybe<T> {
public T Value { get; private set; }
public Something(T value)
{
Value = value;
}
public override string ToString()
{
return Value.ToString();
}
} </syntaxhighlight> Definition der Unit-Methode: <syntaxhighlight lang="csharp"> public static Maybe<T> ToMaybe<T>(this T value) {
return new Something<T>(value);
} </syntaxhighlight>
Definition der Bind-Methode: <syntaxhighlight lang="csharp"> private static Maybe Bind<A, B>(this Maybe<A> m, Func<A, Maybe> f) {
var some = m as Something<A>; return (some == null) ? new Nothing() : f(some.Value);
}
public static Maybe SelectMany<A, B>(this Maybe<A> m, Func<A, Maybe> f) {
return Bind<A, B>(m, f);
}
public static Maybe<C> SelectMany<A, B, C>(this Maybe<A> m, Func<A, Maybe> f, Func<A, B, C> select) {
return m.Bind(x => f(x).Bind(y => select(x,y).ToMaybe()));
} </syntaxhighlight> Verwendung: <syntaxhighlight lang="csharp"> var r = from x in 5.ToMaybe() // Something<int>
from y in new Nothing<int>()
select x + y;
Console.WriteLine(r); // String.Empty </syntaxhighlight>
Definieren eigener Operatoren[Bearbeiten]
Operatoren in LINQ lassen sich erweitern, indem eine passende Erweiterungsmethode bereitgestellt wird. Hierbei können auch Standardoperatoren überschrieben werden.
- Beispiel 1
- Rückgabe von Personen, die zu einem bestimmten Datum Geburtstag haben.
<syntaxhighlight lang="csharp"> public static class PersonExtensions {
public static IEnumerable<TPerson> FilterByBirthday<TPerson>(this IEnumerable<TPerson> persons) where TPerson : Person
{
return FilterByBirthday(persons, DateTime.Now);
}
public static IEnumerable<TPerson> FilterByBirthday<TPerson>(this IEnumerable<TPerson> persons, DateTime date) where TPerson : Person
{
var birthdayPersons = select p in persons
where p.Birthday.Day == date.Day
where p.Birthday.Month == date.Month
select p;
// return the list of persons
foreach(Person p in birthdayPersons)
yield return p;
}
} </syntaxhighlight>
- Aufrufen der neuen Erweiterungsmethode
<syntaxhighlight lang="csharp"> personsToCongratulate = persons.FilterByBirthday(); </syntaxhighlight>
- Beispiel 2
- Definition einer Methode, welche die Menge der ältesten Personen einer Liste zurückliefert. Es soll zudem eine Delegate-Funktion angegeben werden können, um etwa verstorbene Personen auszufiltern.
<syntaxhighlight lang="csharp"> public static class PersonExtensions {
public static IEnumerable<TPerson> Oldest<TPerson>(this IEnumerable<TPerson> source, Func<TPerson, Boolean> predicate) where TPerson : Person
{
// filter Persons for criteria
var persons = from p in source
where predicate(p)
select p;
// determine the age of the oldest persons
int oldestAge = (from p in persons
orderby p.Age descending
select p.Age).First();
// get the list of the oldest persons
var oldestPersons = select p in persons
where p.Age == youngestAge
select p;
// return the list of oldest persons
foreach (Person p in oldestPersons)
yield return p;
}
public static IEnumerable<TPerson> Oldest(this IEnumerable<TPerson> source) where TPerson : Person
{
return Oldest(source, x => true);
}
} </syntaxhighlight>
- Aufrufen der neuen Erweiterungsmethode
<syntaxhighlight lang="csharp"> oldestLivingPersons = persons.Oldest(p => p.Living == true); </syntaxhighlight>
Implementierung eigener LINQ-Provider[Bearbeiten]
Das schreiben eigener LINQ-Provider bietet sich an, wenn ein Service aufgerufen werden soll, welches eine bestimmte Syntax (SQL, XML etc.) verlangt. Um dies zu ermöglichen muss das <syntaxhighlight lang="csharp" inline>IQueryable</syntaxhighlight>-Interface implementiert werden. Über dieses Interface kann der LINQ-Ausdrucksbaum analysiert und in das passende Zielformat umgewandelt werden.
Reactive Extensions[Bearbeiten]
Die Reactive Extensions (kurz: Rx) sind eine Erweiterung von LINQ, welche auf <syntaxhighlight lang="csharp" inline>IObservable<T></syntaxhighlight> statt <syntaxhighlight lang="csharp" inline>IEnumerable<T></syntaxhighlight> arbeitet. Es handelt sich dabei um eine Implementierung des Beobachter-Entwurfsmusters.
| Operationsart gemäß dem CQS-Prinzip | Kommando (Command) | Abfrage (Query) |
|---|---|---|
| Definition | hat Seiteneffekte | liefert Daten zurück |
| Muster | Observer | Iterator |
| Implementierung im .NET Framework | Rx (IObservable) | LINQ (IEnumerable) |
| Muster | Pipes und Filter | Map/Reduce |
| Asynchronität | Alle Kommandos können asynchron implementiert werden. |
Ergebnisse werden mit Hilfe von
zurückgeliefert. |
Die Rx ermöglichen eine Ereignisgesteuerte Programmierung ohne Rückruffunktionen. Gelegentlich werden die Rx dabei als „LINQ to Events“ beschrieben.
Beispiele[Bearbeiten]
LINQ to DataSet[Bearbeiten]
Folgendes Beispiel zeigt die Abfrage einer Tabelle mit Linq. Vorausgesetzt wird eine bestehende Access-Datenbank unter dem Pfad: C:\database.mdb mit einer Tabelle Products, die die Felder ID, Name und EanCode enthält.
Die Tabelle wird als Klasse nachgebildet und mittels Attributen mit Metadaten versehen, die das Mapping auf die Datenbank beschreiben.
Dazu muss in der Projektmappe unter References ein Verweis auf die System.Data.Linq.Dll hinzugefügt werden.
<syntaxhighlight lang="csharp">
using System.Data.Linq.Mapping;
[Table(Name = "Products")]
class Product
{
[Column(Name = "id", IsPrimaryKey = true)]
public int ID;
[Column(Name = "Name")]
public string Name;
[Column(Name = "Ean")]
public string EanCode;
}
</syntaxhighlight>
Nun kann man die Tabelle abfragen. In folgendem Beispiel werden alle Produkte aufgelistet, deren Produktbezeichnung mit einem A beginnt. Die Produkte werden nach ihrer ID sortiert.
<syntaxhighlight lang="csharp"> using System.Configuration; // for ConfigurationManager using System.Data; // for all interface types using System.Data.Common; // for DbProviderFactories
class Foo() {
public static void Main() {
// get connection settings from app.config
var cs = ConfigurationManager.ConnectionStrings["MyConnectionString"];
var factory = DbProviderFactories.GetFactory(cs.ProviderName);
using(IDbConnection connection = new factory.CreateConnection(cs.ConnectionString))
{
connection.Open();
DataContext db = new DataContext(connection);
Table<Product> table = db.GetTable<Product>();
var query = from p in table
where p.Name.StartsWith("A")
orderby p.ID
select p;
foreach (var p in query)
Console.WriteLine(p.Name);
}
}
} </syntaxhighlight>
Alternativ können auch sogenannte Erweiterungsmethoden mit Lambda-Ausdrücken verwendet werden. In solche werden LINQ-Abfragen auch vom Compiler übersetzt.
<syntaxhighlight lang="csharp">
var query = products
.Where(p => p.Name.StartsWith("A"))
.OrderBy(p => p.ID);
foreach (var product in query) {
Console.WriteLine(product.Name);
}
</syntaxhighlight>
Mit der Funktion Single kann ein einzelner Datensatz ermittelt werden. Folgendes Beispiel ermittelt den Datensatz mit der ID 1.
<syntaxhighlight lang="csharp">
Console.WriteLine(products.Single(p => p.ID == 1).Name);
</syntaxhighlight>
Falls aber die Abfrage mehrere Datensätze ermittelt, wird eine InvalidOperationException geworfen.
LINQ to XML[Bearbeiten]
Nachstehend ein Beispiel das zeigt, wie LINQ verwendet werden kann, um Informationen aus einer XML-Datei auszulesen. Als XML-Datei dient folgende XML-Beispieldatei.<ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. MSDN ehemals im Vorlage:Referrer (nicht mehr online verfügbar)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref>
<syntaxhighlight lang="xml"> <?xml version="1.0"?> <PurchaseOrder PurchaseOrderNumber="99503" OrderDate="1999-10-20">
<Address Type="Shipping">
<Name>Ellen Adams</Name>
<Street>123 Maple Street</Street>
<City>Mill Valley</City>
<State>CA</State>
<Zip>10999</Zip>
<Country>USA</Country>
</Address>
<Address Type="Billing">
<Name>Tai Yee</Name>
<Street>8 Oak Avenue</Street>
<City>Old Town</City>
<State>PA</State>
<Zip>95819</Zip>
<Country>USA</Country>
</Address>
<DeliveryNotes>Please leave packages in shed by driveway.</DeliveryNotes>
<Items>
<Item PartNumber="872-AA">
<ProductName>Lawnmower</ProductName>
<Quantity>1</Quantity>
<USPrice>148.95</USPrice>
<Comment>Confirm this is electric</Comment>
</Item>
<Item PartNumber="926-AA">
<ProductName>Baby Monitor</ProductName>
<Quantity>2</Quantity>
<USPrice>39.98</USPrice>
<ShipDate>1999-05-21</ShipDate>
</Item>
</Items>
</PurchaseOrder> </syntaxhighlight> Wollte man beispielsweise die Artikelnummern (PartNumber) aller Einträge vom Typ <Item> auslesen, könnte man folgenden C# Code verwenden<ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. MSDN ehemals im Vorlage:Referrer (nicht mehr online verfügbar)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref>. <syntaxhighlight lang="csharp"> XElement purchaseOrder = XElement.Load("purchase_order.xml");
IEnumerable<string> items =
from item in purchaseOrder.Descendants("Item")
select (string)item.Attribute("PartNumber");
foreach (var item in items) {
Console.WriteLine(partNumbers.ElementAt(i));
} // Output: // 872-AA // 926-AA </syntaxhighlight> Eine andere Möglichkeit, unter Zuhilfenahme einer bedingten Abfrage, wäre alle Artikel auszuwählen, deren Wert mehr als 100 Dollar beträgt. Zusätzlich könnte man das Resultat der Abfrage mittels orderby nach den Artikelnummern, sortieren.
<syntaxhighlight lang="csharp"> XElement purchaseOrder = XElement.Load("purchase_order.xml");
IEnumerable<XElement> items =
from item in purchaseOrder.Descendants("Item")
where (int)item.Element("Quantity") * (decimal)item.Element("USPrice") > 100
orderby (string)item.Element("PartNumber")
select item;
foreach(var item in items) {
Console.WriteLine(item.Attribute("PartNumber").Value);
} // Output: // 872-AA </syntaxhighlight>
LINQ mit Rx[Bearbeiten]
Viele Erweiterungsmethoden von LINQ sind auch in Rx vorhanden. Im folgenden Beispiel wird eine Filterung mit Hilfe der Where()-Klausel durchgeführt: <syntaxhighlight lang="csharp"> using System; using System.Reactive.Subjects; using System.Reactive.Linq;
class Program {
// Helper functions private static Func<int,bool> isEven = n => n%2 == 0; private static Func<int,bool> isOdd = n => !isEven(n); private static Func<int,bool> isDivisibleBy5 = n => n%5 == 0;
static void Main()
{
var subject = new Subject<int>();
using(subject.Where(isEven).Where(isDivisibleBy5).Subscribe(_ => Console.WriteLine("FizzBuzz")))
using(subject.Where(isEven).Where(!isDivisibleBy5).Subscribe(_ => Console.WriteLine("Fizz")))
using(subject.Where(isOdd).Where(isDivisibleBy5).Subscribe(_ => Console.WriteLine("Buzz")))
using(subject.Where(isOdd).Where(!isDivisibleBy5).Subscribe(Console.WriteLine))
{
Observable.Range(1, 100).Subscribe(subject.OnNext);
}
}
} </syntaxhighlight>
Die Erweiterungsmethoden von Rx sind zwar auf eine andere Monade definiert (IObservable<T> statt IEnumerable<T>), da die Bezeichnung der Erweiterungsmethoden jedoch identisch ist, kann auch die Comprehension Syntax von LINQ eingesetzt werden. Eine weitere Möglichkeit ist daher:
<syntaxhighlight lang="csharp"> using System; using System.Text; using System.Reactive.Linq;
class Program {
static string IntToFizzBuzz(int n)
{
return new StringBuilder(8)
.Append((n % 2 == 0) ? "Fizz" : string.Empty)
.Append((n % 5 == 0)? "Buzz" : string.Empty)
.Append((n % 2 != 0 && n % 5 != 0)? n.ToString() : string.Empty)
.ToString();
}
static void Main(string[] args)
{
var numbers = Observable.Range(1, 100);
var fizzBuzz = from n in numbers select IntToFizzBuzz(n);
fizzBuzz.Subscribe(Console.WriteLine);
}
} </syntaxhighlight>
Literatur[Bearbeiten]
- Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Literatur“ ist nicht vorhanden.
Weblinks[Bearbeiten]
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (LINQ Homepage).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Komfortabler Editor zur Erstellung und Ausführung von LINQ-Skripten).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Don Box, Anders Hejlsberg: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft, Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., Informationsseite von Microsoft).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Roger Jennings: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. OakLeaf Systems, Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., Liste verschiedener LINQ-Provider außerhalb von Microsoft).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Jan Welker: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Einführung in LINQ to XML; dreiteilige Artikelserie).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Jan Welker: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Einführung in LINQ to XML; dreiteilige Artikelserie).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Jan Welker: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Einführung in LINQ to XML; dreiteilige Artikelserie).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Robert Mühsig: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Code Inside Blog, Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (deutschsprachige Einführung in LINQ to SQL).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- James Hare: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Tech.Pro, Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden.).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Richard Carr: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. BlackWasp, Skriptfehler: Ein solches Modul „DateTime“ ist nicht vorhanden. ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., Erweiterungsmethoden zur Berechnung von Standardabweichung und Varianz mit LINQ).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
LINQ in anderen Programmiersprachen[Bearbeiten]
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Microsoft ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., LINQ-Variante in F#).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., Abfragen im LINQ-Stil für den HTML5 Web Storage).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., LINQ für JavaScript).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., LINQ to Objects für JavaScript).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Java Streams API<ref name="streams" />
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Codehaus Foundation ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden.).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., LINQ to Objects; kompatibel mit Java 7 Closures).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., LINQ to SQL).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., unterstützt JPA, JDO und SQL).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Jinq<ref>Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.</ref>
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., LINQ für PHP).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., LINQ für PHP).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., Yet Another LINQ to Objects for PHP).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
- Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. In: Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Ehemals im Vorlage:Referrer (nicht mehr online verfügbar) (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden., Python Implementierung für LINQ to Objects und Parallel LINQ to Objects).Vorlage:Toter Link/Core (Seite nicht mehr abrufbar. Suche im Internet Archive)Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden.
Einzelnachweise[Bearbeiten]
<references> <ref name="streams"> [Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden. Skriptfehler: Ein solches Modul „Vorlage:Internetquelle“ ist nicht vorhanden.] Informatech Costa Rica, archiviert vom Vorlage:Referrer (nicht mehr online verfügbar) am 2013-04-01 (Skriptfehler: Ein solches Modul „Multilingual“ ist nicht vorhanden.).Skriptfehler: Ein solches Modul „TemplatePar“ ist nicht vorhanden. </ref> </references>