DocumentDB SQL - Conversione da Linq a SQL

In DocumentDB, usiamo effettivamente SQL per interrogare i documenti. Se stiamo sviluppando .NET, c'è anche un provider LINQ che può essere utilizzato e che può generare SQL appropriato da una query LINQ.

Tipi di dati supportati

In DocumentDB, tutti i tipi primitivi JSON sono supportati nel provider LINQ incluso con DocumentDB .NET SDK che sono i seguenti:

  • Numeric
  • Boolean
  • String
  • Null

Espressione supportata

Le seguenti espressioni scalari sono supportate nel provider LINQ incluso in DocumentDB .NET SDK.

  • Constant Values - Include valori costanti dei tipi di dati primitivi.

  • Property/Array Index Expressions - Le espressioni si riferiscono alla proprietà di un oggetto o di un elemento dell'array.

  • Arithmetic Expressions - Include espressioni aritmetiche comuni su valori numerici e booleani.

  • String Comparison Expression - Include il confronto di un valore di stringa con un valore di stringa costante.

  • Object/Array Creation Expression- Restituisce un oggetto di tipo valore composto o tipo anonimo o un array di tali oggetti. Questi valori possono essere annidati.

Operatori LINQ supportati

Di seguito è riportato un elenco degli operatori LINQ supportati nel provider LINQ incluso con DocumentDB .NET SDK.

  • Select - Le proiezioni si traducono in SQL SELECT inclusa la costruzione di oggetti.

  • Where- I filtri si traducono in SQL WHERE e supportano la traduzione tra &&, || e ! agli operatori SQL.

  • SelectMany- Consente lo svolgimento di array nella clausola SQL JOIN. Può essere utilizzato per concatenare / annidare espressioni per filtrare gli elementi dell'array.

  • OrderBy and OrderByDescending - Si traduce in ORDER BY ascendente / discendente.

  • CompareTo- Si traduce in confronti di intervallo. Comunemente utilizzato per le stringhe poiché non sono confrontabili in .NET.

  • Take - Si traduce in SQL TOP per limitare i risultati di una query.

  • Math Functions - Supporta la traduzione da .NET's Abs, Acos, Asin, Atan, Ceiling, Cos, Exp, Floor, Log, Log10, Pow, Round, Sign, Sin, Sqrt, Tan, Truncate alle funzioni integrate SQL equivalenti.

  • String Functions - Supporta la traduzione da Concat, Contains, EndsWith, IndexOf, Count, ToLower, TrimStart, Replace, Reverse, TrimEnd, StartsWith, SubString, ToUpper di .NET alle funzioni incorporate SQL equivalenti.

  • Array Functions - Supporta la traduzione da Concat, Contains e Count di .NET alle funzioni integrate SQL equivalenti.

  • Geospatial Extension Functions - Supporta la traduzione dai metodi stub Distance, Within, IsValid e IsValidDetailed alle funzioni incorporate SQL equivalenti.

  • User-Defined Extension Function - Supporta la traduzione dal metodo stub UserDefinedFunctionProvider.Invoke alla funzione definita dall'utente corrispondente.

  • Miscellaneous- Supporta la traduzione di operatori di coalescenza e condizionali. Può tradurre Contains in String CONTAINS, ARRAY_CONTAINS o SQL IN a seconda del contesto.

Diamo un'occhiata a un esempio in cui utilizzeremo .Net SDK. Di seguito sono riportati i tre documenti che prenderemo in considerazione per questo esempio.

Nuovo cliente 1

{ 
   "name": "New Customer 1", 
   "address": { 
      "addressType": "Main Office", 
      "addressLine1": "123 Main Street", 
		
      "location": { 
         "city": "Brooklyn", 
         "stateProvinceName": "New York" 
      },
	  
      "postalCode": "11229", 
      "countryRegionName": "United States" 
   }, 
}

Nuovo cliente 2

{ 
   "name": "New Customer 2", 
	
   "address": {
      "addressType": "Main Office", 
      "addressLine1": "678 Main Street", 
		
      "location": { 
         "city": "London", 
         "stateProvinceName": " London " 
      }, 
	  
      "postalCode": "11229", 
      "countryRegionName": "United Kingdom" 
   }, 
}

Nuovo cliente 3

{ 
   "name": "New Customer 3", 
	
   "address": { 
      "addressType": "Main Office", 
      "addressLine1": "12 Main Street", 
		
      "location": { 
         "city": "Brooklyn", 
         "stateProvinceName": "New York" 
      },
	  
      "postalCode": "11229", 
      "countryRegionName": "United States" 
   },
}

Di seguito è riportato il codice in cui eseguiamo query utilizzando LINQ. Abbiamo definito una query LINQ inq, ma non verrà eseguito finché non eseguiremo .ToList su di esso.

private static void QueryDocumentsWithLinq(DocumentClient client) { 
   Console.WriteLine(); 
   Console.WriteLine("**** Query Documents (LINQ) ****"); 
   Console.WriteLine();  
   Console.WriteLine("Quering for US customers (LINQ)"); 
   var q = 
      from d in client.CreateDocumentQuery<Customer>(collection.DocumentsLink) 
      where d.Address.CountryRegionName == "United States" 
		
   select new { 
      Id = d.Id, 
      Name = d.Name, 
      City = d.Address.Location.City 
   };
   
   var documents = q.ToList();  
   Console.WriteLine("Found {0} US customers", documents.Count); 
	
   foreach (var document in documents) { 
      var d = document as dynamic; 
      Console.WriteLine(" Id: {0}; Name: {1}; City: {2}", d.Id, d.Name, d.City); 
   }
   
   Console.WriteLine(); 
}

L'SDK convertirà la nostra query LINQ nella sintassi SQL per DocumentDB, generando una clausola SELECT e WHERE basata sulla nostra sintassi LINQ.

Chiamiamo le query precedenti dall'attività CreateDocumentClient.

private static async Task CreateDocumentClient() { 
   // Create a new instance of the DocumentClient 
   using (var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey)) { 
      database = client.CreateDatabaseQuery("SELECT * FROM c WHERE c.id = 
         'myfirstdb'").AsEnumerable().First(); 
      collection = client.CreateDocumentCollectionQuery(database.CollectionsLink, 
         "SELECT * FROM c WHERE c.id = 'MyCollection'").AsEnumerable().First();  
      QueryDocumentsWithLinq(client); 
   } 
}

Quando il codice precedente viene eseguito, produce il seguente output.

**** Query Documents (LINQ) **** 
 
Quering for US customers (LINQ) 
Found 2 US customers 
   Id: 7e9ad4fa-c432-4d1a-b120-58fd7113609f; Name: New Customer 1; City: Brooklyn 
   Id: 34e9873a-94c8-4720-9146-d63fb7840fad; Name: New Customer 1; City: Brooklyn