Libreria client dei database elastici con Entity FrameworkElastic Database client library with Entity Framework

Questo documento illustra le modifiche necessarie in un'applicazione Entity Framework per l'integrazione con le funzionalità degli strumenti del database elastico.This document shows the changes in an Entity Framework application that are needed to integrate with the Elastic Database tools. Vengono descritti in particolare la gestione delle mappe partizioni e il routing dipendente dai dati con l'approccio Code First di Entity Framework.The focus is on composing shard map management and data-dependent routing with the Entity Framework Code First approach. L'esercitazione Code First per un nuovo database per Entity Framework servirà da esempio nell'intero documento.The Code First - New Database tutorial for EF serves as the running example throughout this document. Il codice di esempio che accompagna questo documento fa parte del set di esempi sugli strumenti dei database elastici negli esempi di codice di Visual Studio.The sample code accompanying this document is part of elastic database tools' set of samples in the Visual Studio Code Samples.

Download ed esecuzione del codice di esempioDownloading and Running the Sample Code

Per scaricare il codice per questo articolo:To download the code for this article:

  • È richiesto Visual Studio 2012 o versione successiva.Visual Studio 2012 or later is required.
  • Scaricare l'esempio Elastic DB Tools for Azure SQL - Entity Framework Integration (Strumenti del database elastico per SQL di Azure - Integrazione con Entity Framework) da MSDN.Download the Elastic DB Tools for Azure SQL - Entity Framework Integration sample from MSDN. Decomprimere l'esempio in un percorso a piacere.Unzip the sample to a location of your choosing.
  • Avviare Visual Studio.Start Visual Studio.
  • In Visual Studio selezionare File -> Apri progetto/soluzione.In Visual Studio, select File -> Open Project/Solution.
  • Nella finestra di dialogo Apri progetto passare all'esempio scaricato e selezionare EntityFrameworkCodeFirst.sln per aprirlo.In the Open Project dialog, navigate to the sample you downloaded and select EntityFrameworkCodeFirst.sln to open the sample.

Per eseguire l'esempio è necessario creare tre database vuoti nel database SQL di Azure:To run the sample, you need to create three empty databases in Azure SQL Database:

  • Database di gestione delle mappe partizioniShard Map Manager database
  • Database partizione 1Shard 1 database
  • Database partizione 2Shard 2 database

Dopo aver creato questi database, riempire i segnaposto nel file Program.cs con il nome del server di database SQL di Azure, i nomi dei database e le credenziali per la connessione ai database.Once you have created these databases, fill in the place holders in Program.cs with your Azure SQL DB server name, the database names, and your credentials to connect to the databases. Compilare la soluzione in Visual Studio.Build the solution in Visual Studio. Visual Studio scaricherà i pacchetti NuGet necessari per la libreria client dei database elastici, Entity Framework e la gestione degli errori temporanei come parte del processo di compilazione.Visual Studio downloads the required NuGet packages for the elastic database client library, Entity Framework, and Transient Fault handling as part of the build process. Verificare che per la soluzione sia abilitato il ripristino dei pacchetti NuGet.Make sure that restoring NuGet packages is enabled for your solution. Per abilitare questa impostazione, fare clic con il pulsante destro del mouse sul file di soluzione in Esplora soluzioni di Visual Studio.You can enable this setting by right-clicking on the solution file in the Visual Studio Solution Explorer.

Flussi di lavoro di Entity FrameworkEntity Framework workflows

Gli sviluppatori Entity Framework si basano su uno dei quattro seguenti flussi di lavoro per compilare le applicazioni e garantire la persistenza degli oggetti applicazione:Entity Framework developers rely on one of the following four workflows to build applications and to ensure persistence for application objects:

  • Code First (nuovo database): lo sviluppatore Entity Framework crea il modello nel codice dell'applicazione ed Entity Framework genera il database a partire dal codice.Code First (New Database): The EF developer creates the model in the application code and then EF generates the database from it.
  • Code First (database esistente): lo sviluppatore consente a Entity Framework di generare il codice dell'applicazione per il modello da un database esistente.Code First (Existing Database): The developer lets EF generate the application code for the model from an existing database.
  • Model First: lo sviluppatore crea il modello in Entity Framework Designer e quindi Entity Framework crea il database a partire dal modello.Model First: The developer creates the model in the EF designer and then EF creates the database from the model.
  • Database First: lo sviluppatore usa gli strumenti di Entity Framework per dedurre il modello da un database esistente.Database First: The developer uses EF tooling to infer the model from an existing database.

Tutti questi approcci si basano sulla classe DbContext per gestire in modo trasparente le connessioni di database e lo schema del database per un'applicazione.All these approaches rely on the DbContext class to transparently manage database connections and database schema for an application. Costruttori diversi della classe base DbContext offrono livelli di controllo diversi sulla creazione delle connessioni, il bootstrap del database e la creazione dello schema.Different constructors on the DbContext base class allow for different levels of control over connection creation, database bootstrapping, and schema creation. Le difficoltà sorgono principalmente dal fatto che la gestione delle connessioni di database fornita da Entity Framework si sovrappone alle funzionalità di gestione connessioni delle interfacce di routing dipendente dai dati fornite dalla libreria client dei database elastici.Challenges arise primarily from the fact that the database connection management provided by EF intersects with the connection management capabilities of the data-dependent routing interfaces provided by the elastic database client library.

Presupposti degli strumenti dei database elasticiElastic database tools assumptions

Per le definizioni dei termini, vedere il glossario degli strumenti del database elastico.For term definitions, see Elastic Database tools glossary.

La libreria client dei database elastici consente di definire partizioni dei dati applicativi denominate shardlet.With elastic database client library, you define partitions of your application data called shardlets. Gli shardlet sono identificati da una chiave di partizionamento orizzontale e sono mappati a database specifici.Shardlets are identified by a sharding key and are mapped to specific databases. Un'applicazione può disporre di tutti i database necessari e distribuire gli shardlet per fornire capacità o prestazioni sufficienti in base ai requisiti aziendali correnti.An application may have as many databases as needed and distribute the shardlets to provide enough capacity or performance given current business requirements. Il mapping dei valori delle chiavi di partizionamento orizzontale ai database è archiviato in una mappa partizioni fornita dalle API client dei database elastici.The mapping of sharding key values to the databases is stored by a shard map provided by the elastic database client APIs. Questa funzionalità è denominata Gestione mappe partizioni.This capability is called Shard Map Management, or SMM for short. 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à è conosciuta come routing dipendente dai dati.This capability is known as data-dependent routing.

Il gestore delle mappe partizioni protegge gli utenti da visualizzazioni incoerenti nei dati degli shardlet potenzialmente provocate dall'esecuzione simultanea di operazioni di gestione degli shardlet, ad esempio la rilocazione di dati da una partizione all'altra.The shard map manager protects users from inconsistent views into shardlet data that can occur when concurrent shardlet management operations (such as relocating data from one shard to another) are happening. A tale scopo, le mappe di partizionamento gestite dalla libreria client gestiscono le connessioni al database per un'applicazione.To do so, the shard maps managed by the client library broker the database connections for an application. In questo modo la funzionalità mappa partizioni può terminare automaticamente una connessione di database quando le operazioni di gestione delle partizioni potrebbero influire sullo shardlet per cui è stata creata la connessione.This allows the shard map functionality to automatically kill a database connection when shard management operations could impact the shardlet that the connection has been created for. Questo approccio richiede l'integrazione con alcune funzionalità di Entity Framework, ad esempio la creazione di nuove connessioni a partire da una connessione esistente per verificare l'esistenza del database.This approach needs to integrate with some of EF’s functionality, such as creating new connections from an existing one to check for database existence. In generale, è stato osservato che i costruttori DbContext standard funzionano in modo affidabile solo per le connessioni di database chiuse che possono essere clonate in sicurezza per le operazioni di Entity Framework.In general, our observation has been that the standard DbContext constructors only work reliably for closed database connections that can safely be cloned for EF work. Il principio di progettazione dei database elastici prevede invece solo la gestione delle connessioni aperte.The design principle of elastic database instead is to only broker opened connections. Si potrebbe pensare che chiudere una connessione gestita dalla libreria client prima di passarla al costruttore DbContext di Entity Framework consenta di risolvere il problema.One might think that closing a connection brokered by the client library before handing it over to the EF DbContext may solve this issue. Tuttavia, chiudendo la connessione e affidandone la riapertura a Entity Framework, si rinuncia alla convalida e ai controlli di coerenza eseguiti dalla libreria.However, by closing the connection and relying on EF to reopen it, one foregoes the validation and consistency checks performed by the library. La funzionalità per le migrazioni di Entity Framework, tuttavia, usa queste connessioni per gestire lo schema del database sottostante in modo trasparente per l'applicazione.The migrations functionality in EF, however, uses these connections to manage the underlying database schema in a way that is transparent to the application. La soluzione ideale prevede di mantenere e combinare tutte le funzionalità della libreria client dei database elastici ed Entity Framework nella stessa applicazione.Ideally, you will retain and combine all these capabilities from both the elastic database client library and EF in the same application. La seguente sezione illustra queste proprietà e i requisiti in maggiore dettaglio.The following section discusses these properties and requirements in more detail.

RequisitiRequirements

Quando si usano sia le API della libreria client dei database elastici che di Entity Framework, si vogliono conservare le seguenti proprietà:When working with both the elastic database client library and Entity Framework APIs, you want to retain the following properties:

  • Scalabilità orizzontale: per aggiungere o rimuovere database dal livello dati dell'applicazione partizionata a seconda delle necessità, per soddisfare le esigenze di capacità dell'applicazione.Scale-out: To add or remove databases from the data tier of the sharded application as necessary for the capacity demands of the application. Ciò significa controllo sulla creazione e sull'eliminazione dei database e uso delle API del gestore delle mappe partizioni del database elastico per gestire i database e i mapping degli shardlet.This means control over the creation and deletion of databases and using the elastic database shard map manager APIs to manage databases, and mappings of shardlets.
  • Coerenza: l'applicazione usa il partizionamento orizzontale e si serve delle funzionalità di routing dipendente dai dati della libreria client.Consistency: The application employs sharding, and uses the data-dependent routing capabilities of the client library. Per evitare il danneggiamento dei dati o la restituzione di risultati di query errati, le connessioni vengono gestite tramite il gestore delle mappe partizioni.To avoid corruption or wrong query results, connections are brokered through the shard map manager. In questo modo vengono mantenute anche la convalida e la coerenza.This also retains validation and consistency.
  • Code First: per mantenere la praticità del paradigma Code First di Entity Framework.Code First: To retain the convenience of EF’s code first paradigm. In Code First, le classi nell'applicazione vengono mappate in modo trasparente alle strutture di database sottostanti.In Code First, classes in the application are mapped transparently to the underlying database structures. Il codice dell'applicazione interagisce con DbSet che mascherano la maggior parte degli aspetti coinvolti nell'elaborazione di database sottostante.The application code interacts with DbSets that mask most aspects involved in the underlying database processing.
  • Schema: Entity Framework gestisce la creazione iniziale dello schema del database e la successiva evoluzione dello schema mediante migrazioni.Schema: Entity Framework handles initial database schema creation and subsequent schema evolution through migrations. Conservando queste funzionalità, adattare l'applicazione in base all'evoluzione dei dati è molto semplice.By retaining these capabilities, adapting your app is easy as the data evolves.

Le seguenti informazioni aggiuntive illustrano come soddisfare questi requisiti per le applicazioni Code First usando gli strumenti dei database elastici.The following guidance instructs how to satisfy these requirements for Code First applications using elastic database tools.

Routing dipendente dai dati con DbContext di Entity FrameworkData-dependent routing using EF DbContext

Le connessioni di database con Entity Framework vengono in genere gestite tramite sottoclassi di DbContext.Database connections with Entity Framework are typically managed through subclasses of DbContext. Creare le sottoclassi derivandole da DbContext.Create these subclasses by deriving from DbContext. Questa è la posizione in cui si definiscono i DbSet che implementano le raccolte supportate da database di oggetti CLR per l'applicazione.This is where you define your DbSets that implement the database-backed collections of CLR objects for your application. Nel contesto del routing dipendente dai dati è possibile identificare diverse proprietà utili che non sono necessariamente rilevanti per altri scenari di applicazioni Code First di Entity Framework:In the context of data-dependent routing, you can identify several helpful properties that do not necessarily hold for other EF code first application scenarios:

  • Il database esiste già ed è stato registrato nella mappa partizioni del database elastico.The database already exists and has been registered in the elastic database shard map.
  • Lo schema dell'applicazione è già stato distribuito al database (come illustrato di seguito).The schema of the application has already been deployed to the database (explained below).
  • Le connessioni di routing dipendente dai dati al database vengono gestite dalla mappa partizioni.Data-dependent routing connections to the database are brokered by the shard map.

Per integrare i DbContext con il routing dipendente dai dati per la scalabilità orizzontale:To integrate DbContexts with data-dependent routing for scale-out:

  1. Creare connessioni di database fisiche mediante le interfacce client del database elastico del gestore delle mappe partizioniCreate physical database connections through the elastic database client interfaces of the shard map manager,
  2. Eseguire il wrapping della connessione con la sottoclasse DbContextWrap the connection with the DbContext subclass
  3. Passare la connessione alle classi base DbContext per assicurare che venga eseguita anche tutta l'elaborazione sul lato Entity Framework.Pass the connection down into the DbContext base classes to ensure all the processing on the EF side happens as well.

Il seguente esempio di codice illustra questo approccio.The following code example illustrates this approach. Il codice è disponibile anche nel progetto di Visual Studio associato.(This code is also in the accompanying Visual Studio project)

public class ElasticScaleContext<T> : DbContext
{
public DbSet<Blog> Blogs { get; set; }
…

    // C'tor for data-dependent routing. This call opens a validated connection 
    // routed to the proper shard by the shard map manager. 
    // Note that the base class c'tor call fails for an open connection
    // if migrations need to be done and SQL credentials are used. This is the reason for the 
    // separation of c'tors into the data-dependent routing case (this c'tor) and the internal c'tor for new shards.
    public ElasticScaleContext(ShardMap shardMap, T shardingKey, string connectionStr)
        : base(CreateDDRConnection(shardMap, shardingKey, connectionStr), 
        true /* contextOwnsConnection */)
    {
    }

    // Only static methods are allowed in calls into base class c'tors.
    private static DbConnection CreateDDRConnection(
    ShardMap shardMap, 
    T shardingKey, 
    string connectionStr)
    {
        // No initialization
        Database.SetInitializer<ElasticScaleContext<T>>(null);

        // Ask shard map to broker a validated connection for the given key
        SqlConnection conn = shardMap.OpenConnectionForKey<T>
                            (shardingKey, connectionStr, ConnectionOptions.Validate);
        return conn;
    }    

Punti principaliMain points

  • Un nuovo costruttore sostituisce il costruttore predefinito nella sottoclasse DbContextA new constructor replaces the default constructor in the DbContext subclass
  • Il nuovo costruttore accetta gli argomenti necessari per il routing dipendente dai dati mediante la libreria client dei database elastici:The new constructor takes the arguments that are required for data-dependent routing through elastic database client library:

    • 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,
    • una stringa di connessione con le credenziali per la connessione di routing dipendente dai dati alla partizione.a connection string with the credentials for the data-dependent routing connection to the shard.
  • La chiamata al costruttore di classe base accetta una deviazione in un metodo statico che esegue tutti i passaggi necessari per il routing dipendente dai dati.The call to the base class constructor takes a detour into a static method that performs all the steps necessary for data-dependent routing.

    • Usa la chiamata OpenConnectionForKey delle interfacce client dei database elastici sulla mappa partizioni per stabilire una connessione aperta.It uses the OpenConnectionForKey call of the elastic database client interfaces on the shard map to establish an open connection.
    • La mappa partizioni crea la connessione aperta alla partizione che contiene lo shardlet per la chiave di partizionamento orizzontale specificata.The shard map creates the open connection to the shard that holds the shardlet for the given sharding key.
    • Tale connessione aperta viene nuovamente passata al costruttore di classe base di DbContext per indicare che Entity Framework deve usare quella anziché crearne automaticamente una nuova.This open connection is passed back to the base class constructor of DbContext to indicate that this connection is to be used by EF instead of letting EF create a new connection automatically. In questo modo, la connessione è stata contrassegnata dall’API client dei database elastici al fine di garantire coerenza durante le operazioni di gestione della mappa partizioni.This way the connection has been tagged by the elastic database client API so that it can guarantee consistency under shard map management operations.

Nel proprio codice usare il nuovo costruttore per la sottoclasse DbContext anziché il costruttore predefinito.Use the new constructor for your DbContext subclass instead of the default constructor in your code. Di seguito è fornito un esempio:Here is an example:

// Create and save a new blog.

Console.Write("Enter a name for a new blog: "); 
var name = Console.ReadLine(); 

using (var db = new ElasticScaleContext<int>( 
                        sharding.ShardMap,  
                        tenantId1,  
                        connStrBldr.ConnectionString)) 
{ 
    var blog = new Blog { Name = name }; 
    db.Blogs.Add(blog); 
    db.SaveChanges(); 

    // Display all Blogs for tenant 1 
    var query = from b in db.Blogs 
                orderby b.Name 
                select b; 
 … 
}

Il nuovo costruttore apre la connessione alla partizione che contiene i dati per lo shardlet identificato dal valore di tenantid1.The new constructor opens the connection to the shard that holds the data for the shardlet identified by the value of tenantid1. Il codice nel blocco using resta invariato per accedere al DbSet per i blog usando Entity Framework sulla partizione per tenantid1.The code in the using block stays unchanged to access the DbSet for blogs using EF on the shard for tenantid1. Questo modifica la semantica per il codice nel blocco using in modo tale che tutte le operazioni di database abbiano come ambito la partizione in cui è conservato tenantid1 .This changes semantics for the code in the using block such that all database operations are now scoped to the one shard where tenantid1 is kept. Ad esempio, una query LINQ sul DbSet dei blog restituirebbe solo i blog archiviati nella partizione corrente, ma non quelli archiviati in altre partizioni.For instance, a LINQ query over the blogs DbSet would only return blogs stored on the current shard, but not the ones stored on other shards.

Gestione degli errori temporaneiTransient faults handling

Il team Microsoft Patterns & Practices ha pubblicato un articolo sul blocco applicazione per la gestione degli errori temporanei.The Microsoft Patterns & Practices team published the The Transient Fault Handling Application Block. La libreria viene usata con la libreria client della scalabilità elastica in combinazione con Entity Framework.The library is used with elastic scale client library in combination with EF. È però necessario assicurarsi che qualsiasi eccezione temporanea venga restituita in una posizione in cui ci si può accertare che dopo un errore temporaneo venga usato il nuovo costruttore, in modo che qualsiasi nuovo tentativo di connessione venga effettuato usando i costruttori modificati.However, ensure that any transient exception returns to a place where you can ensure that the new constructor is being used after a transient fault so that any new connection attempt is made using the constructors you tweaked. In caso contrario, la connessione alla partizione corretta non è garantita, né esistono garanzie che la connessione venga mantenuta in caso di modifica della mappa partizioni.Otherwise, a connection to the correct shard is not guaranteed, and there are no assurances the connection is maintained as changes to the shard map occur.

L'esempio di codice seguente illustra il possibile uso di un criterio di ripetizione SQL sui nuovi costruttori della sottoclasse DbContext :The following code sample illustrates how a SQL retry policy can be used around the new DbContext subclass constructors:

SqlDatabaseUtils.SqlRetryPolicy.ExecuteAction(() => 
{ 
    using (var db = new ElasticScaleContext<int>( 
                            sharding.ShardMap,  
                            tenantId1,  
                            connStrBldr.ConnectionString)) 
        { 
                var blog = new Blog { Name = name }; 
                db.Blogs.Add(blog); 
                db.SaveChanges(); 
        … 
        } 
    }); 

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. Questo approccio corrisponde alle informazioni aggiuntive per le transazioni di Entity Framework e avviate dall'utente; vedere l'argomento relativo alle limitazioni per le strategie di esecuzione con ripetizione dei tentativi (vedere Entity Framework 6 e versioni successive).This approach is similar to the guidance for EF and user-initiated transactions (see Limitations with Retrying Execution Strategies (EF6 onwards). Entrambe le situazioni richiedono che il programma applicativo controlli l'ambito in cui viene restituita l'eccezione temporanea: per riaprire la transazione o (come mostrato) ricreare il contesto dal costruttore corretto che usa la libreria client dei database elastici.Both situations require that the application program controls the scope to which the transient exception returns: to either reopen the transaction, or (as shown) recreate the context from the proper constructor that uses the elastic database client library.

La necessità di controllare la posizione a cui si viene riportati dalle eccezioni temporanee all'interno dell'ambito preclude anche l'uso dell'oggetto SqlAzureExecutionStrategy in dotazione con Entity Framework.The need to control where transient exceptions take us back in scope also precludes the use of the built-in SqlAzureExecutionStrategy that comes with EF. SqlAzureExecutionStrategy riaprirebbe una connessione, ma non userebbe OpenConnectionForKey, di conseguenza verrebbe ignorata qualsiasi forma di convalida eseguita come parte della chiamata OpenConnectionForKey.SqlAzureExecutionStrategy would reopen a connection but not use OpenConnectionForKey and therefore bypass all the validation that is performed as part of the OpenConnectionForKey call. L'esempio di codice usa invece l'oggetto DefaultExecutionStrategy , anch'esso incluso in Entity Framework.Instead, the code sample uses the built-in DefaultExecutionStrategy that also comes with EF. A differenza di SqlAzureExecutionStrategy, funziona correttamente con i criteri di ripetizione derivanti dalla gestione degli errori temporanei.As opposed to SqlAzureExecutionStrategy, it works correctly in combination with the retry policy from Transient Fault Handling. I criteri di esecuzione vengono impostati nella classe ElasticScaleDbConfiguration .The execution policy is set in the ElasticScaleDbConfiguration class. Si noti che si è deciso di non usare DefaultSqlExecutionStrategy perché suggerisce l'uso di SqlAzureExecutionStrategy in caso di eccezioni temporanee, situazione che causerebbe un comportamento errato, come spiegato in precedenza.Note that we decided not to use DefaultSqlExecutionStrategy since it suggests using SqlAzureExecutionStrategy if transient exceptions occur - which would lead to wrong behavior as discussed. Per altre informazioni sui diversi criteri di ripetizione ed Entity Framework, vedere l'articolo relativo alla resilienza delle connessioni in Entity Framework.For more information on the different retry policies and EF, see Connection Resiliency in EF.

Riscritture dei costruttoriConstructor rewrites

Gli esempi di codice precedenti illustrano le riscritture del costruttore predefinito necessarie perché l'applicazione possa usare il routing dipendente dai dati con Entity Framework.The code examples above illustrate the default constructor re-writes required for your application in order to use data-dependent routing with the Entity Framework. La seguente tabella generalizza questo approccio per altri costruttori.The following table generalizes this approach to other constructors.

Costruttore correnteCurrent Constructor Costruttore riscritto per i datiRewritten Constructor for data Costruttore baseBase Constructor NoteNotes
MyContext()MyContext() ElasticScaleContext(ShardMap, TKey)ElasticScaleContext(ShardMap, TKey) DbContext(DbConnection, bool)DbContext(DbConnection, bool) La connessione deve essere una funzione della mappa partizioni e della chiave di routing dipendente dai dati.The connection needs to be a function of the shard map and the data-dependent routing key. È necessario ignorare la creazione automatica della connessione da parte di Entity Framework e gestire la connessione mediante la mappa partizioni.You need to by-pass automatic connection creation by EF and instead use the shard map to broker the connection.
MyContext(string)MyContext(string) ElasticScaleContext(ShardMap, TKey)ElasticScaleContext(ShardMap, TKey) DbContext(DbConnection, bool)DbContext(DbConnection, bool) La connessione è una funzione della mappa partizioni e della chiave di routing dipendente dai dati.The connection is a function of the shard map and the data-dependent routing key. Non è possibile usare una stringa di connessione o un nome di database fisso, in quanto ignoreranno la convalida da parte della mappa partizioni.A fixed database name or connection string does not work as they by-pass validation by the shard map.
MyContext(DbCompiledModel)MyContext(DbCompiledModel) ElasticScaleContext(ShardMap, TKey, DbCompiledModel)ElasticScaleContext(ShardMap, TKey, DbCompiledModel) DbContext(DbConnection, DbCompiledModel, bool)DbContext(DbConnection, DbCompiledModel, bool) Verrà creata la connessione per la mappa partizioni e per la chiave di partizionamento specificate con il modello fornito.The connection gets created for the given shard map and sharding key with the model provided. Il modello compilato verrà passato al costruttore base.The compiled model is passed on to the base c’tor.
MyContext(DbConnection, bool)MyContext(DbConnection, bool) ElasticScaleContext(ShardMap, TKey, bool)ElasticScaleContext(ShardMap, TKey, bool) DbContext(DbConnection, bool)DbContext(DbConnection, bool) La connessione deve essere dedotta dalla mappa partizioni e dalla chiave.The connection needs to be inferred from the shard map and the key. Non può essere fornita come input (a meno che l'input non usi già la mappa partizioni e la chiave).It cannot be provided as an input (unless that input was already using the shard map and the key). Viene passato il valore booleano.The Boolean is passed on.
MyContext(string, DbCompiledModel)MyContext(string, DbCompiledModel) ElasticScaleContext(ShardMap, TKey, DbCompiledModel)ElasticScaleContext(ShardMap, TKey, DbCompiledModel) DbContext(DbConnection, DbCompiledModel, bool)DbContext(DbConnection, DbCompiledModel, bool) La connessione deve essere dedotta dalla mappa partizioni e dalla chiave.The connection needs to be inferred from the shard map and the key. Non può essere fornita come input (a meno che l'input non usi la mappa partizioni e la chiave).It cannot be provided as an input (unless that input was using the shard map and the key). Viene passato il modello compilato.The compiled model is passed on.
MyContext(ObjectContext, bool)MyContext(ObjectContext, bool) ElasticScaleContext(ShardMap, TKey, ObjectContext, bool)ElasticScaleContext(ShardMap, TKey, ObjectContext, bool) DbContext(ObjectContext, bool)DbContext(ObjectContext, bool) Il nuovo costruttore deve garantire che qualsiasi connessione in ObjectContext passato come input venga reinstradata a una connessione gestita da Scalabilità elastica.The new constructor needs to ensure that any connection in the ObjectContext passed as an input is re-routed to a connection managed by Elastic Scale. La descrizione dettagliata di ObjectContext esula dall'ambito di questo documento.A detailed discussion of ObjectContexts is beyond the scope of this document.
MyContext(DbConnection, DbCompiledModel, bool)MyContext(DbConnection, DbCompiledModel, bool) ElasticScaleContext(ShardMap, TKey, DbCompiledModel, bool)ElasticScaleContext(ShardMap, TKey, DbCompiledModel, bool) DbContext(DbConnection, DbCompiledModel, bool);DbContext(DbConnection, DbCompiledModel, bool); La connessione deve essere dedotta dalla mappa partizioni e dalla chiave.The connection needs to be inferred from the shard map and the key. Non può essere fornita come input (a meno che l'input non usi già la mappa partizioni e la chiave).The connection cannot be provided as an input (unless that input was already using the shard map and the key). Il modello e il valore booleano verranno passati al costruttore di classe base.Model and Boolean are passed on to the base class constructor.

Distribuzione dello schema partizione tramite migrazioni di Entity FrameworkShard schema deployment through EF migrations

La gestione automatica dello schema è una funzionalità disponibile in Entity Framework.Automatic schema management is a convenience provided by the Entity Framework. Nel contesto di applicazioni che usano gli strumenti dei database elastici è desiderabile mantenere questa funzionalità per il provisioning automatico dello schema alle nuove partizioni quando si aggiungono database all'applicazione partizionata.In the context of applications using elastic database tools, you want to retain this capability to automatically provision the schema to newly created shards when databases are added to the sharded application. Il caso di utilizzo principale è l'aumento della capacità al livello dati per le applicazioni partizionate mediante Entity Framework.The primary use case is to increase capacity at the data tier for sharded applications using EF. L'uso delle le funzionalità di Entity Framework per la gestione dello schema riduce le attività di amministrazione di database necessarie per un'applicazione partizionata basata su Entity Framework.Relying on EF’s capabilities for schema management reduces the database administration effort with a sharded application built on EF.

La distribuzione dello schema tramite migrazioni di Entity Framework funziona al meglio con le connessioni non aperte.Schema deployment through EF migrations works best on unopened connections. Si tratta di uno scenario diverso rispetto al routing dipendente dai dati, che usa la connessione aperta fornita dall'API client dei database elastici.This is in contrast to the scenario for data-dependent routing that relies on the opened connection provided by the elastic database client API. Un’altra differenza è il requisito di coerenza: sebbene sia opportuno garantire la coerenza per tutte le connessioni di routing dipendente dai dati per la protezione dalle modifiche simultanee alla mappa partizioni, questo non rappresenta un problema nel caso della distribuzione iniziale dello schema in un nuovo database non ancora registrato nella mappa partizioni e non ancora allocato per contenere shardlet.Another difference is the consistency requirement: While desirable to ensure consistency for all data-dependent routing connections to protect against concurrent shard map manipulation, it is not a concern with initial schema deployment to a new database that has not yet been registered in the shard map, and not yet been allocated to hold shardlets. Per questi scenari è pertanto possibile usare le normali connessioni di database anziché il routing dipendente dai dati.You can therefore rely on regular database connections for this scenario, as opposed to data-dependent routing.

Questo conduce a un approccio in cui la distribuzione dello schema tramite migrazioni di Entity Framework è strettamente legata alla registrazione del nuovo database come partizione nella mappa partizioni dell'applicazione.This leads to an approach where schema deployment through EF migrations is tightly coupled with the registration of the new database as a shard in the application’s shard map. L'approccio è basato sui seguenti prerequisiti:This relies on the following prerequisites:

  • Il database è già stato creato.The database has already been created.
  • Il database è vuoto, non contiene schemi utente o dati utente.The database is empty - it holds no user schema and no user data.
  • Il database non è ancora accessibile alle API client dei database elastici per il routing dipendente dai dati.The database cannot yet be accessed through the elastic database client APIs for data-dependent routing.

Se questi prerequisiti sono soddisfatti, è possibile creare una normale connessione SqlConnection non aperta per avviare le migrazioni di Entity Framework per la distribuzione dello schema.With these prerequisites in place, you can create a regular un-opened SqlConnection to kick off EF migrations for schema deployment. Il seguente esempio di codice illustra questo approccio.The following code sample illustrates this approach.

    // Enter a new shard - i.e. an empty database - to the shard map, allocate a first tenant to it  
    // and kick off EF intialization of the database to deploy schema 

    public void RegisterNewShard(string server, string database, string connStr, int key) 
    { 

        Shard shard = this.ShardMap.CreateShard(new ShardLocation(server, database)); 

        SqlConnectionStringBuilder connStrBldr = new SqlConnectionStringBuilder(connStr); 
        connStrBldr.DataSource = server; 
        connStrBldr.InitialCatalog = database; 

        // Go into a DbContext to trigger migrations and schema deployment for the new shard. 
        // This requires an un-opened connection. 
        using (var db = new ElasticScaleContext<int>(connStrBldr.ConnectionString)) 
        { 
            // Run a query to engage EF migrations 
            (from b in db.Blogs 
                select b).Count(); 
        } 

        // Register the mapping of the tenant to the shard in the shard map. 
        // After this step, data-dependent routing on the shard map can be used 

        this.ShardMap.CreatePointMapping(key, shard); 
    } 

Questo esempio illustra il metodo RegisterNewShard , che registra la partizione nella mappa partizioni, distribuisce lo schema tramite migrazioni di Entity Framework e archivia il mapping di una chiave di partizionamento orizzontale nella partizione.This sample shows the method RegisterNewShard that registers the shard in the shard map, deploys the schema through EF migrations, and stores a mapping of a sharding key to the shard. Si basa su un costruttore della sottoclasse DbContext (ElasticScaleContext nell'esempio) che accetta come input una stringa di connessione SQL.It relies on a constructor of the DbContext subclass (ElasticScaleContext in the sample) that takes a SQL connection string as input. Il codice di questo costruttore è semplice, come illustrato nel seguente esempio:The code of this constructor is straight-forward, as the following example shows:

    // C'tor to deploy schema and migrations to a new shard 
    protected internal ElasticScaleContext(string connectionString) 
        : base(SetInitializerForConnection(connectionString)) 
    { 
    } 

    // Only static methods are allowed in calls into base class c'tors 
    private static string SetInitializerForConnection(string connnectionString) 
    { 
        // You want existence checks so that the schema can get deployed 
        Database.SetInitializer<ElasticScaleContext<T>>( 
    new CreateDatabaseIfNotExists<ElasticScaleContext<T>>()); 

        return connnectionString; 
    } 

Si sarebbe potuta usare la versione del costruttore ereditata dalla classe base,One might have used the version of the constructor inherited from the base class. ma il codice deve garantire che per la connessione venga usato l'inizializzatore predefinito di Entity Framework.But the code needs to ensure that the default initializer for EF is used when connecting. Da qui la breve deviazione nel metodo statico prima della chiamata al costruttore di classe base con la stringa di connessione.Hence the short detour into the static method before calling into the base class constructor with the connection string. Notare che la registrazione delle partizioni deve essere eseguita in un dominio applicativo o in un processo diverso, per garantire l'assenza di conflitti con le impostazioni dell'inizializzatore per Entity Framework.Note that the registration of shards should run in a different app domain or process to ensure that the initializer settings for EF do not conflict.

LimitazioniLimitations

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

  • Prima di usare la libreria client del database elastico, è necessario eseguire la migrazione delle applicazioni Entity Framework che usano LocalDb a un normale database di SQL Server.EF applications that use LocalDb first need to migrate to a regular SQL Server database before using elastic database client library. Con LocalDbnon è possibile scalare orizzontalmente un'applicazione mediante il partizionamento orizzontale con la scalabilità elastica.Scaling out an application through sharding with Elastic Scale is not possible with LocalDb. Per lo sviluppo è comunque possibile usare LocalDb.Note that development can still use LocalDb.
  • Le modifiche all'applicazione che implicano modifiche dello schema del database devono passare attraverso le migrazioni di Entity Framework su tutte le partizioni.Any changes to the application that imply database schema changes need to go through EF migrations on all shards. Il codice di esempio per questo documento non illustra come eseguire questa operazione.The sample code for this document does not demonstrate how to do this. Provare a usare Update-Database con un parametro ConnectionString per eseguire l'iterazione su tutte le partizioni oppure estrarre lo script T-SQL per la migrazione in sospeso usando Update-Database con l'opzione –Script e applicare lo script T-SQL alle partizioni.Consider using Update-Database with a ConnectionString parameter to iterate over all shards; or extract the T-SQL script for the pending migration using Update-Database with the -Script option and apply the T-SQL script to your 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, it is assumed that all of its database processing is contained within a single shard as identified by the sharding key provided by the request. Questo presupposto, tuttavia, non è sempre valido,However, this assumption does not always hold true. ad esempio quando non è possibile rendere disponibile una chiave di partizionamento orizzontale.For example, when it is not possible to make a sharding key available. A questo scopo, la libreria client fornisce la classe MultiShardQuery che implementa un'astrazione delle connessioni per l'esecuzione di query su più partizioni.To address this, the client library provides the MultiShardQuery class that implements a connection abstraction for querying over several shards. L'uso di MultiShardQuery in combinazione con Entity Framework esula dall'ambito di questo documentoLearning to use the MultiShardQuery in combination with EF is beyond the scope of this document

ConclusioniConclusion

Seguendo le procedure descritte in questo documento, le applicazioni Entity Framework possono usufruire della funzionalità di routing dipendente dai dati della libreria client dei database elastici mediante il refactoring dei costruttori delle sottoclassi DbContext usate nelle applicazioni stesse.Through the steps outlined in this document, EF applications can use the elastic database client library's capability for data-dependent routing by refactoring constructors of the DbContext subclasses used in the EF application. Questo limita il numero di modifiche necessarie nelle posizioni in cui sono già presenti classi DbContext.This limits the changes required to those places where DbContext classes already exist. Inoltre, le applicazioni Entity Framework possono continuare a usufruire della distribuzione automatica dello schema combinando le operazioni che richiamano le migrazioni Entity Framework con la registrazione di nuove partizioni e mapping nella mappa partizioni.In addition, EF applications can continue to benefit from automatic schema deployment by combining the steps that invoke the necessary EF migrations with the registration of new shards and mappings in the shard map.

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.