Freigeben über


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 und Truncate 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 und TrimStart aus .NET in die entsprechenden integrierten Zeichenfolgenfunktionen.
  • Arrayfunktionen: Unterstützt die Übersetzung von Concat, Contains und Count aus .NET in die entsprechenden integrierten Arrayfunktionen.
  • Geospatial-Erweiterungsfunktionen: Unterstützt die Übersetzung von Distance, IsValid, IsValidDetailed und Within 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. Kann Contains 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