Utilizzo della libreria client dei database elastici con DapperUsing elastic database client library with Dapper

Questo documento è rivolto agli sviluppatori che si basano su Dapper per creare applicazioni, ma desiderano avvalersi degli strumenti dei database elastici per creare applicazioni che implementano il partizionamento per la scalabilità orizzontale del livello dati.This document is for developers that rely on Dapper to build applications, but also want to embrace elastic database tooling to create applications that implement sharding to scale out their data tier. Questo documento illustra le modifiche da apportare nelle applicazioni basate su Dapper per l'integrazione con gli strumenti dei database elastici.This document illustrates the changes in Dapper-based applications that are necessary to integrate with elastic database tools. L'obiettivo è comporre la gestione delle partizioni dei database elastici e il routing dipendente dai dati con Dapper.Our focus is on composing the elastic database shard management and data-dependent routing with Dapper.

Codice di esempio: Strumenti dei database elastici per il database SQL di Azure - Integrazione con Dapper.Sample Code: Elastic database tools for Azure SQL Database - Dapper integration.

L'integrazione di Dapper e DapperExtensions con la libreria client dei database elastici per il database SQL di Azure è semplice.Integrating Dapper and DapperExtensions with the elastic database client library for Azure SQL Database is easy. Le applicazioni possono usare il routing dipendente dai dati modificando la creazione e l'apertura di nuovi oggetti SqlConnection per usare la chiamata a OpenConnectionForKey dalla libreria client.Your applications can use data-dependent routing by changing the creation and opening of new SqlConnection objects to use the OpenConnectionForKey call from the client library. Questo limita le modifiche nell'applicazione solo ai punti in cui vengono create e aperte nuove connessioni.This limits changes in your application to only where new connections are created and opened.

Informazioni generali su DapperDapper overview

Dapper è un mapper object-relational.Dapper is an object-relational mapper. Esegue il mapping degli oggetti .NET dell'applicazione con un database relazionale e viceversa.It maps .NET objects from your application to a relational database (and vice versa). La prima parte del codice di esempio illustra come integrare la libreria client dei database elastici con applicazioni basate su Dapper.The first part of the sample code illustrates how you can integrate the elastic database client library with Dapper-based applications. La seconda parte del codice di esempio illustra come eseguire l’integrazione quando si usano Dapper e DapperExtensions.The second part of the sample code illustrates how to integrate when using both Dapper and DapperExtensions.

La funzionalità di mapper in Dapper fornisce metodi di estensione per le connessioni di database che semplificano l'invio di istruzioni T-SQL per l'esecuzione o per l'esecuzione di query del database.The mapper functionality in Dapper provides extension methods on database connections that simplify submitting T-SQL statements for execution or querying the database. Ad esempio, Dapper consente di eseguire il mapping tra gli oggetti .NET e i parametri delle istruzioni SQL per le chiamate Execute o di usare i risultati delle query SQL negli oggetti .NET mediante chiamate Query da Dapper.For instance, Dapper makes it easy to map between your .NET objects and the parameters of SQL statements for Execute calls, or to consume the results of your SQL queries into .NET objects using Query calls from Dapper.

Quando si usa DapperExtensions, non è più necessario fornire le istruzioni SQL.When using DapperExtensions, you no longer need to provide the SQL statements. I metodi di estensione, ad esempio GetList o Insert per la connessione di database, creano le istruzioni SQL dietro le quinte.Extensions methods such as GetList or Insert over the database connection create the SQL statements behind the scenes.

Un altro vantaggio offerto da Dapper e anche da DapperExtensions è il controllo della creazione della connessione di database da parte dell'applicazione.Another benefit of Dapper and also DapperExtensions is that the application controls the creation of the database connection. Ciò consente di interagire con la libreria client dei database elastici che negozia le connessioni di database in base al mapping tra shardlet e database.This helps interact with the elastic database client library which brokers database connections based on the mapping of shardlets to databases.

Per ottenere gli assembly Dapper, vedere la pagina relativa a Dapper dot net.To get the Dapper assemblies, see Dapper dot net. Per le estensioni Dapper, vedere la pagina relativa a DapperExtensions.For the Dapper extensions, see DapperExtensions.

Panoramica della libreria client dei database elasticiA quick Look at the elastic database client library

Con libreria client dei database elastici è possibile definire partizioni di dati di applicazione denominate shardlet, eseguirne il mapping con i database e identificarli in base a chiavi di partizionamento orizzontale.With the elastic database client library, you define partitions of your application data called shardlets, map them to databases, and identify them by sharding keys. È possibile disporre di tutti i database desiderati e distribuire gli shardlet su tali database.You can have as many databases as you need and distribute your shardlets across these databases. Il mapping dei valori delle chiavi di partizionamento orizzontale ai database è archiviato in una mappa partizioni fornita dalle API della libreria.The mapping of sharding key values to the databases is stored by a shard map provided by the library’s APIs. Questa funzionalità è denominata gestione mappe partizioni.This capability is called shard map management. La mappa partizioni funge anche da gestore delle connessioni di database per le richieste che contengono una chiave di partizionamento orizzontale.The shard map also serves as the broker of database connections for requests that carry a sharding key. Questa funzionalità è indicata come routing dipendente dai dati.This capability is referred to as data-dependent routing.

Mappe di partizione e routing dipendente dai dati

Il gestore mappe partizioni protegge gli utenti da visualizzazioni non coerenti in dati di shardlet che possono verificarsi quando vengono eseguite operazioni di gestione shardlet simultanee nei database.The shard map manager protects users from inconsistent views into shardlet data that can occur when concurrent shardlet management operations are happening on the databases. A tale scopo, le mappe partizioni gestiscono le connessioni al database per un'applicazione compilata con la libreria.To do so, the shard maps broker the database connections for an application built with the library. Se esiste il rischio che le operazioni di gestione delle partizioni abbiano impatto sullo shardlet, in questo modo la funzionalità delle mappe di partizioni può terminare automaticamente una connessione al database.When shard management operations could impact the shardlet, this allows the shard map functionality to automatically kill a database connection.

Anziché usare il sistema tradizionale per creare connessioni per Dapper, è necessario usare il metodo OpenConnectionForKey.Instead of using the traditional way to create connections for Dapper, you need to use the OpenConnectionForKey method. Ciò garantisce che vengano eseguite tutte le convalide e vengano gestite correttamente le connessioni durante lo spostamento di dati tra le partizioni.This ensures that all the validation takes place and connections are managed properly when any data moves between shards.

Requisiti per l'integrazione con DapperRequirements for Dapper integration

Quando si usano sia la libreria client dei database elastici che le API di Dapper, si desidera mantenere le seguenti proprietà:When working with both the elastic database client library and the Dapper APIs, you want to retain the following properties:

  • Scalabilità orizzontale: si desidera aggiungere o rimuovere database dal livello dati dell'applicazione partizionata a seconda delle necessità per soddisfare le esigenze di capacità dell'applicazione.Scale out: We want to add or remove databases from the data tier of the sharded application as necessary for the capacity demands of the application.
  • Coerenza: poiché nell'applicazione viene implementata la scalabilità orizzontale con il partizionamento orizzontale, è necessario eseguire il routing dipendente dai dati.Consistency: Since the application is scaled out using sharding, you need to perform data-dependent routing. A tale scopo, è possibile usare le funzionalità di routing dipendente dai dati della libreria.We want to use the data-dependent routing capabilities of the library to do so. In particolare, si desidera mantenere le garanzie di convalida e coerenza fornite dalle connessioni negoziate tramite il gestore mappe partizioni per evitare problemi di danneggiamento o di risultati di query non corretti.In particular, you want to retain the validation and consistency guarantees provided by connections that are brokered through the shard map manager in order to avoid corruption or wrong query results. Ciò garantisce che le connessioni a un determinato shardlet vengano rifiutate o arrestate se ad esempio lo shardlet è attualmente spostato in una partizione diversa tramite API di suddivisione/unione.This ensures that connections to a given shardlet are rejected or stopped if (for instance) the shardlet is currently moved to a different shard using Split/Merge APIs.
  • Mapping degli oggetti: si desidera mantenere i vantaggi dei mapping forniti da Dapper per la conversione tra le classi nell'applicazione e le strutture di database sottostanti.Object Mapping: We want to retain the convenience of the mappings provided by Dapper to translate between classes in the application and the underlying database structures.

La seguente sezione fornisce indicazioni per tali requisiti per le applicazioni basate su Dapper e DapperExtensions.The following section provides guidance for these requirements for applications based on Dapper and DapperExtensions.

Indicazioni tecnicheTechnical Guidance

Routing dipendente dai dati con DapperData-dependent routing with Dapper

Con Dapper l'applicazione è in genere responsabile della creazione e l'apertura delle connessioni al database sottostante.With Dapper, the application is typically responsible for creating and opening the connections to the underlying database. Sulla base di un tipo T fornito dall'applicazione, Dapper restituisce risultati di query come raccolte .NET di tipo T. Dapper esegue il mapping tra le righe di risultati di T-SQL e gli oggetti di tipo T. Analogamente, Dapper esegue il mapping tra oggetti .NET e parametri o valori SQL per istruzioni Data Manipulation Language (DML).Given a type T by the application, Dapper returns query results as .NET collections of type T. Dapper performs the mapping from the T-SQL result rows to the objects of type T. Similarly, Dapper maps .NET objects into SQL values or parameters for data manipulation language (DML) statements. Dapper offre questa funzionalità tramite i metodi di estensione nel normale oggetto SqlConnection delle librerie client SQL ADO.NET.Dapper offers this functionality via extension methods on the regular SqlConnection object from the ADO .NET SQL Client libraries. Anche la connessione SQL restituita dalle API di scalabilità elastica per record dei dati di individuazione sono normali oggetti SqlConnection.The SQL connection returned by the Elastic Scale APIs for DDR are also regular SqlConnection objects. In questo modo è possibile usare direttamente le estensioni Dapper sul tipo restituito dall'API di record dei dati della libreria client, perché anche in questo caso si tratta di una semplice connessione client SQL.This allows us to directly use Dapper extensions over the type returned by the client library’s DDR API, as it is also a simple SQL Client connection.

Queste osservazioni semplificano l'utilizzo delle connessioni negoziate dalla libreria client dei database elastici per Dapper.These observations make it straightforward to use connections brokered by the elastic database client library for Dapper.

Questo esempio di codice (dall'esempio di accompagnamento) illustra il metodo in cui la chiave di partizionamento viene fornita dall'applicazione alla libreria per negoziare la connessione al partizionamento corretto.This code example (from the accompanying sample) illustrates the approach where the sharding key is provided by the application to the library to broker the connection to the right shard.

using (SqlConnection sqlconn = shardingLayer.ShardMap.OpenConnectionForKey(
                 key: tenantId1, 
                 connectionString: connStrBldr.ConnectionString, 
                 options: ConnectionOptions.Validate))
{
    var blog = new Blog { Name = name };
    sqlconn.Execute(@"
                  INSERT INTO
                        Blog (Name)
                        VALUES (@name)", new { name = blog.Name }
                    );
}

La chiamata all'API OpenConnectionForKey sostituisce la creazione predefinita e l'apertura di una connessione client SQL.The call to the OpenConnectionForKey API replaces the default creation and opening of a SQL Client connection. La chiamata a OpenConnectionForKey accetta gli argomenti necessari per il routing dipendente dai dati:The OpenConnectionForKey call takes the arguments that are required for data-dependent routing:

  • La mappa partizioni per l'accesso alle interfacce di routing dipendente dai datiThe shard map to access the data-dependent routing interfaces
  • La chiave di partizionamento orizzontale per l'identificazione dello shardletThe sharding key to identify the shardlet
  • Le credenziali (nome utente e password) per la connessione alla partizioneThe credentials (user name and password) to connect to the shard

L'oggetto mappa partizioni crea una connessione alla partizione che contiene lo shardlet per la chiave di partizionamento orizzontale specificata.The shard map object creates a connection to the shard that holds the shardlet for the given sharding key. Le API della libreria client dei database elastici aggiungono inoltre un tag alla connessione per implementare le garanzie di coerenza.The elastic database client APIs also tag the connection to implement its consistency guarantees. Poiché la chiamata a OpenConnectionForKey restituisce un normale oggetto di connessione client SQL, la chiamata successiva al metodo di estensione Execute da Dapper segue la procedura Dapper standard.Since the call to OpenConnectionForKey returns a regular SQL Client connection object, the subsequent call to the Execute extension method from Dapper follows the standard Dapper practice.

Le query funzionano in modo molto simile: si apre innanzitutto la connessione usando OpenConnectionForKey dall'API client.Queries work very much the same way - you first open the connection using OpenConnectionForKey from the client API. Si usano quindi i normali metodi di estensione Dapper per il mapping tra i risultati della query SQL negli oggetti .NET:Then you use the regular Dapper extension methods to map the results of your SQL query into .NET objects:

using (SqlConnection sqlconn = shardingLayer.ShardMap.OpenConnectionForKey(
                key: tenantId1, 
                connectionString: connStrBldr.ConnectionString, 
                options: ConnectionOptions.Validate ))
{    
       // Display all Blogs for tenant 1
       IEnumerable<Blog> result = sqlconn.Query<Blog>(@"
                            SELECT * 
                            FROM Blog
                            ORDER BY Name");

       Console.WriteLine("All blogs for tenant id {0}:", tenantId1);
       foreach (var item in result)
       {
            Console.WriteLine(item.Name);
        }
}

Si noti che il blocco using con la connessione di record di dati di individuazione definisce l'ambito di tutte le operazioni di database all'interno del blocco per la partizione in cui viene mantenuto tenantId1.Note that the using block with the DDR connection scopes all database operations within the block to the one shard where tenantId1 is kept. La query restituisce solo blog archiviati nella partizione corrente, ma non quelli archiviati nelle altre partizioni.The query only returns blogs stored on the current shard, but not the ones stored on any other shards.

Routing dipendente dai dati con Dapper e DapperExtensionsData-dependent routing with Dapper and DapperExtensions

Dapper viene fornito con un ecosistema di estensioni aggiuntive che garantiscono praticità e astrazione dal database durante lo sviluppo di applicazioni di database.Dapper comes with an ecosystem of additional extensions that can provide further convenience and abstraction from the database when developing database applications. Un esempio è rappresentato da DapperExtensions.DapperExtensions is an example.

L'uso di DapperExtensions nell'applicazione non comporta la modifica della modalità di creazione e gestione delle connessioni di database.Using DapperExtensions in your application does not change how database connections are created and managed. È comunque responsabilità dell'applicazione aprire le connessioni e sono previsti normali oggetti di connessione client SQL dai metodi di estensione.It is still the application’s responsibility to open connections, and regular SQL Client connection objects are expected by the extension methods. È possibile basarsi sul metodo OpenConnectionForKey come illustrato in precedenza.We can rely on the OpenConnectionForKey as outlined above. Come mostrato nei seguenti esempi di codice, come unica differenza non è necessario scrivere le istruzioni T-SQL:As the following code samples show, the only change is that you no longer have to write the T-SQL statements:

using (SqlConnection sqlconn = shardingLayer.ShardMap.OpenConnectionForKey(
                key: tenantId2, 
                connectionString: connStrBldr.ConnectionString, 
                options: ConnectionOptions.Validate))
{
       var blog = new Blog { Name = name2 };
       sqlconn.Insert(blog);
}

Questo è l'esempio di codice per la query:And here is the code sample for the query:

using (SqlConnection sqlconn = shardingLayer.ShardMap.OpenConnectionForKey(
                key: tenantId2, 
                connectionString: connStrBldr.ConnectionString, 
                options: ConnectionOptions.Validate))
{
       // Display all Blogs for tenant 2
       IEnumerable<Blog> result = sqlconn.GetList<Blog>();
       Console.WriteLine("All blogs for tenant id {0}:", tenantId2);
       foreach (var item in result)
       {
           Console.WriteLine(item.Name);
       }
}

Gestione degli errori temporaneiHandling transient faults

Il team Microsoft Patterns & Practices ha pubblicato un articolo relativo al blocco di applicazioni per la gestione degli errori temporanei per consentire agli sviluppatori di applicazioni di attenuare le comuni condizioni di errori temporanei rilevate durante l'esecuzione nel cloud.The Microsoft Patterns & Practices team published the Transient Fault Handling Application Block to help application developers mitigate common transient fault conditions encountered when running in the cloud. Per ulteriori informazioni, vedere Perseveranza, il segreto di tutti i successi: uso del Blocco di applicazioni per la gestione degli errori temporanei.For more information, see Perseverance, Secret of All Triumphs: Using the Transient Fault Handling Application Block.

L'esempio di codice si basa sulla libreria di errori temporanei per proteggersi da questo tipo di errori.The code sample relies on the transient fault library to protect against transient faults.

SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() =>
{
   using (SqlConnection sqlconn = 
      shardingLayer.ShardMap.OpenConnectionForKey(tenantId2, connStrBldr.ConnectionString, ConnectionOptions.Validate))
      {
          var blog = new Blog { Name = name2 };
          sqlconn.Insert(blog);
      }
});

SqlDatabaseUtils.SqlRetryPolicy nel codice precedente viene definito come SqlDatabaseTransientErrorDetectionStrategy con un numero di tentativi pari a 10 e un tempo di attesa tra i tentativi pari a 5 secondi.SqlDatabaseUtils.SqlRetryPolicy in the code above is defined as a SqlDatabaseTransientErrorDetectionStrategy with a retry count of 10, and 5 seconds wait time between retries. Se si usano le transazioni, assicurarsi che l'ambito delle ripetizioni risalga all'inizio della transazione in caso di errore temporaneo.If you are using transactions, make sure that your retry scope goes back to the beginning of the transaction in the case of a transient fault.

LimitazioniLimitations

Gli approcci descritti in questo documento implicano due limitazioni:The approaches outlined in this document entail a couple of limitations:

  • Il codice di esempio per questo documento non illustra come gestire lo schema tra partizioni.The sample code for this document does not demonstrate how to manage schema across shards.
  • Data una richiesta, si presuppone che tutta la relativa elaborazione di database sia contenuta in una singola partizione identificata dalla chiave di partizionamento orizzontale fornita dalla richiesta.Given a request, we assume that all its database processing is contained within a single shard as identified by the sharding key provided by the request. Tuttavia, questo presupposto non ha sempre valore, ad esempio quando non è possibile rendere disponibile una chiave di partizionamento orizzontale.However, this assumption does not always hold, for example, when it is not possible to make a sharding key available. Per risolvere questo problema, la libreria client dei database elastici include la classe MultiShardQuery.To address this, the elastic database client library includes the MultiShardQuery class. Questa classe implementa un'astrazione di connessione per l'esecuzione di query su più partizioni.The class implements a connection abstraction for querying over several shards. L'uso di MultiShardQuery in combinazione con Dapper esula dall'ambito di questo documento.Using MultiShardQuery in combination with Dapper is beyond the scope of this document.

ConclusioniConclusion

Le applicazioni che usano Dapper e DapperExtensions possono trarre vantaggio facilmente dagli strumenti dei database elastici del database SQL di Azure.Applications using Dapper and DapperExtensions can easily benefit from elastic database tools for Azure SQL Database. Tramite le procedure descritte in questo documento, tali applicazioni possono usare la funzionalità dello strumento per il routing dipendente dai dati modificando la creazione e l'apertura di nuovi oggetti SqlConnection per usare la chiamata a OpenConnectionForKey della libreria client dei database elastici.Through the steps outlined in this document, those applications can use the tool's capability for data-dependent routing by changing the creation and opening of new SqlConnection objects to use the OpenConnectionForKey call of the elastic database client library. In questo modo si limitano le modifiche dell'applicazione ai punti in cui vengono create e aperte nuove connessioni.This limits the application changes required to those places where new connections are created and opened.

Risorse aggiuntiveAdditional resources

Se non si usano gli strumenti di database elastici,Not using elastic database tools yet? vedere la Guida introduttiva.Check out our Getting Started Guide. Se ci sono domande, è possibile visitare il forum sul database SQL mentre è possibile inserire le richieste di nuove funzionalità nel forum relativo a commenti e suggerimenti sul database SQL.For questions, please reach out to us on the SQL Database forum and for feature requests, please add them to the SQL Database feedback forum.