LINQ to NoSQL-Übersetzung in Azure Cosmos DB for NoSQL
GILT FÜR: NoSQL
Der Azure Cosmos DB Abfrageanbieter führt ein bestmögliches Mapping von einer LINQ-Abfrage in eine Azure Cosmos DB for NoSQL-Abfrage durch. Wenn Sie die aus LINQ übersetzte NoSQL-Abfrage erhalten möchten, verwenden Sie die ToString()
-Methode für das generierte IQueryable
-Objekt. Bei der folgenden Beschreibung wird davon ausgegangen, dass Sie mit den Grundsätzen von LINQ vertraut sind. Zusätzlich zu LINQ unterstützt Azure Cosmos DB auch Entity Framework Core, das mit API für NoSQL eingesetzt werden kann.
Hinweis
Es wird empfohlen, die neueste Version des .NET SDK (Microsoft.Azure.Cosmos
) zu verwenden.
Das Typsystem der Abfrageanbieter unterstützt nur die primitiven JSON-Typen: numeric
, Boolean
, string
und null
.
Der Abfrageanbieter unterstützt die folgenden skalaren Ausdrücke:
Konstante Werte, einschließlich konstanter Werte der primitiven Datentypen zum Auswertungszeitpunkt der Abfrage.
Indexausdrücke auf Eigenschaften/Arrays, die sich auf die Eigenschaft eines Objekts oder eines Arrayelements beziehen. Beispiel:
family.Id; family.children[0].familyName; family.children[0].grade;
int n = 1; family.children[n].grade;
Arithmetische Ausdrücke, einschließlich allgemeiner arithmetischer Ausdrücke auf numerische und boolesche Werte.
2 * family.children[0].grade; x + y;
Vergleichsausdrücke für Zeichenfolgen, einschließlich Vergleiche von Zeichenfolgenwerten mit konstanten Zeichenfolgen.
mother.familyName.StringEquals("Wakefield");
string s = "Rob"; string e = "in"; string c = "obi"; child.givenName.StartsWith(s); child.givenName.EndsWith(e); child.givenName.Contains(c);
Erstellungsausdrücke für Objekte/Arrays, die ein Objekt mit einem Verbundwerttyp oder anonymen Typ bzw. ein Array solcher Objekte zurückgeben. Diese Werte können geschachtelt werden.
new Parent { familyName = "Wakefield", givenName = "Robin" }; new { first = 1, second = 2 }; //an anonymous type with two fields new int[] { 3, child.grade, 5 };
Verwenden von LINQ
Sie können eine LINQ-Abfrage mit GetItemLinqQueryable
erstellen. In diesem Beispiel wird die LINQ-Abfragegenerierung und die asynchrone Ausführung mit FeedIterator
gezeigt:
using FeedIterator<Book> setIterator = container.GetItemLinqQueryable<Book>()
.Where(b => b.Title == "War and Peace")
.ToFeedIterator<Book>());
//Asynchronous query execution
while (setIterator.HasMoreResults)
{
foreach(var item in await setIterator.ReadNextAsync()){
{
Console.WriteLine(item.cost);
}
}
Unterstützte LINQ-Operatoren
Der im NoSQL .NET SDK enthaltene LINQ-Anbieter unterstützt die folgenden Operatoren:
- Select: Projektionen, einschließlich Objektkonstruktion, werden in SELECT übersetzt.
- Where: Filter werden zu WHERE übersetzt und unterstützen die Übersetzung von
&&
,||
und!
in die SQL-Operatoren. - SelectMany: Ermöglicht das Entladen von Arrays in die JOIN-Klausel. Wird zum Verketten oder Verschachteln von Ausdrücken zum Filtern von Arrayelementen verwendet.
- OrderBy und OrderByDescending: Übersetzung in ORDER BY mit ASC oder DESC.
- Die Operatoren Count, Sum, Min, Max und Average für die Aggregation und deren asynchrone Entsprechungen CountAsync, SumAsync, MinAsync, MaxAsync und AverageAsync.
- CompareTo: Übersetzung in Bereichsvergleiche. Dieser Operator wird häufig für Zeichenfolgen verwendet, da sie nicht in .NET vergleichbar sind.
- Skip und Take: Übersetzung in OFFSET und LIMIT zum Einschränken von Ergebnissen einer Abfrage und zum Durchführen der Paginierung.
- Mathematische Funktionen: Unterstützt die Übersetzung von
Abs
,Acos
,Asin
,Atan
,Ceiling
,Cos
,Exp
,Floor
,Log
,Log10
,Pow
,Round
,Sign
,Sin
,Sqrt
,Tan
undTruncate
aus .NET in die entsprechenden integrierten mathematischen Funktionen. - Zeichenfolgenfunktionen: Unterstützt die Übersetzung von
Concat
,Contains
,Count
,EndsWith
,IndexOf
,Replace
,Reverse
,StartsWith
,SubString
,ToLower
,ToUpper
,TrimEnd
undTrimStart
aus .NET in die entsprechenden integrierten Zeichenfolgenfunktionen. - Arrayfunktionen: Unterstützt die Übersetzung von
Concat
,Contains
undCount
aus .NET in die entsprechenden integrierten Arrayfunktionen. - Geospatial-Erweiterungsfunktionen: Unterstützt die Übersetzung von
Distance
,IsValid
,IsValidDetailed
undWithin
aus .NET in die entsprechenden integrierten Geofunktionen. - Erweiterungsfunktion für benutzerdefinierte Funktion: Unterstützt die Übersetzung aus der Stubmethode CosmosLinq.InvokeUserDefinedFunction in die entsprechende benutzerdefinierte Funktion.
- Sonstiges: Unterstützt die Übersetzung von
Coalesce
und bedingten Operatoren. KannContains
je nach Kontext in die Zeichenfolge CONTAINS, ARRAY_CONTAINS oder IN übersetzen.
Beispiele
Die folgenden Beispiele zeigen, wie einige der Standard-LINQ-Abfrageoperatoren in Abfragen in Azure Cosmos DB übersetzt werden.
Select-Operator
Die Syntax ist input.Select(x => f(x))
, wobei f
ein skalarer Ausdruck ist. input
ist in diesem Fall ein IQueryable
-Objekt.
Select-Operator, Beispiel 1:
LINQ Lambda-Ausdruck
input.Select(family => family.parents[0].familyName);
NoSQL
SELECT VALUE f.parents[0].familyName FROM Families f
Select-Operator, Beispiel 2:
LINQ Lambda-Ausdruck
input.Select(family => family.children[0].grade + c); // c is an int variable
NoSQL
SELECT VALUE f.children[0].grade + c FROM Families f
Select-Operator, Beispiel 3:
LINQ Lambda-Ausdruck
input.Select(family => new { name = family.children[0].familyName, grade = family.children[0].grade + 3 });
NoSQL
SELECT VALUE { "name":f.children[0].familyName, "grade": f.children[0].grade + 3 } FROM Families f
SelectMany-Operator
Die Syntax lautet input.SelectMany(x => f(x))
, wobei f
ein skalarer Ausdruck ist, der einen Containertyp zurückgibt.
LINQ Lambda-Ausdruck
input.SelectMany(family => family.children);
NoSQL
SELECT VALUE child FROM child IN Families.children
Where-Operator
Die Syntax ist input.Where(x => f(x))
, wobei f
ein skalarer Ausdruck ist, der einen booleschen Wert zurückgibt.
Where-Operator, Beispiel 1:
LINQ Lambda-Ausdruck
input.Where(family=> family.parents[0].familyName == "Wakefield");
NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield"
Where-Operator, Beispiel 2:
LINQ Lambda-Ausdruck
input.Where( family => family.parents[0].familyName == "Wakefield" && family.children[0].grade < 3);
NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield" AND f.children[0].grade < 3
Zusammengesetzte NoSQL-Abfragen
Sie können die oben angegebenen Operatoren zu komplexeren Abfragen zusammensetzen. Da Azure Cosmos DB geschachtelte Container unterstützt, können Sie die Zusammensetzung entweder verketten oder schachteln.
Verkettung
Die Syntax ist input(.|.SelectMany())(.Select()|.Where())*
. Eine verkettete Abfrage kann mit einer optionalen SelectMany
-Abfrage beginnen, gefolgt von mehreren Select
- oder Where
-Operatoren.
Verkettung, Beispiel 1:
LINQ Lambda-Ausdruck
input.Select(family => family.parents[0]) .Where(parent => parent.familyName == "Wakefield");
NoSQL
SELECT * FROM Families f WHERE f.parents[0].familyName = "Wakefield"
Verkettung, Beispiel 2:
LINQ Lambda-Ausdruck
input.Where(family => family.children[0].grade > 3) .Select(family => family.parents[0].familyName);
NoSQL
SELECT VALUE f.parents[0].familyName FROM Families f WHERE f.children[0].grade > 3
Verkettung, Beispiel 3:
LINQ Lambda-Ausdruck
input.Select(family => new { grade=family.children[0].grade}). Where(anon=> anon.grade < 3);
NoSQL
SELECT * FROM Families f WHERE ({grade: f.children[0].grade}.grade > 3)
Verkettung, Beispiel 4:
LINQ Lambda-Ausdruck
input.SelectMany(family => family.parents) .Where(parent => parents.familyName == "Wakefield");
NoSQL
SELECT * FROM p IN Families.parents WHERE p.familyName = "Wakefield"
Verschachtelung
Die Syntax ist input.SelectMany(x=>x.Q())
, wobei Q
ein Select
-, SelectMany
- oder Where
-Operator ist.
Bei einer geschachtelten Abfrage wird die innere Abfrage auf jedes Element des äußeren Containers angewendet. Ein wichtiges Feature ist, dass die innere Abfrage wie bei einer Selbstverknüpfung auf die Felder der Elemente im äußeren Container verweisen kann.
Verschachtelung, Beispiel 1:
LINQ Lambda-Ausdruck
input.SelectMany(family=> family.parents.Select(p => p.familyName));
NoSQL
SELECT VALUE p.familyName FROM Families f JOIN p IN f.parents
Verschachtelung, Beispiel 2:
LINQ Lambda-Ausdruck
input.SelectMany(family => family.children.Where(child => child.familyName == "Jeff"));
NoSQL
SELECT * FROM Families f JOIN c IN f.children WHERE c.familyName = "Jeff"
Verschachtelung, Beispiel 3:
LINQ Lambda-Ausdruck
input.SelectMany(family => family.children.Where( child => child.familyName == family.parents[0].familyName));
NoSQL
SELECT * FROM Families f JOIN c IN f.children WHERE c.familyName = f.parents[0].familyName