Använda klientbiblioteket för elastisk databas med Dapper
Gäller för:Azure SQL Database
Det här dokumentet är till för utvecklare som använder Dapper för att skapa program, men som också vill använda elastiska databasverktyg för att skapa program som implementerar horisontell partitionering för att skala ut sin datanivå. Det här dokumentet illustrerar de ändringar i Dapper-baserade program som krävs för att integrera med elastiska databasverktyg. Vårt fokus ligger på att skapa elastisk databashantering och databeroende routning med Dapper.
Exempelkod: Elastiska databasverktyg för Azure SQL Database – Dapper-integrering.
Det är enkelt att integrera Dapper och DapperExtensions med klientbiblioteket för elastisk databas för Azure SQL Database. Dina program kan använda databeroende routning genom att ändra skapande och öppning av nya Sql Anslut ion-objekt för att använda Open Anslut ionForKey-anropet från klientbiblioteket. Detta begränsar ändringar i ditt program till endast där nya anslutningar skapas och öppnas.
Översikt över Dapper
Dapper är en objektrelationsmappare. Den mappar .NET-objekt från ditt program till en relationsdatabas (och vice versa). Den första delen av exempelkoden visar hur du kan integrera klientbiblioteket för elastisk databas med Dapper-baserade program. Den andra delen av exempelkoden visar hur du integrerar när du använder både Dapper och DapperExtensions.
Mappningsfunktionen i Dapper tillhandahåller tilläggsmetoder för databasanslutningar som förenklar sändning av T-SQL-instruktioner för körning eller frågekörning av databasen. Dapper gör det till exempel enkelt att mappa mellan dina .NET-objekt och parametrarna för SQL-instruktioner för Körningsanrop , eller att använda resultatet av dina SQL-frågor till .NET-objekt med hjälp av frågeanrop från Dapper.
När du använder DapperExtensions behöver du inte längre ange SQL-uttrycken. Tilläggsmetoder som GetList eller Insert via databasanslutningen skapar SQL-uttrycken i bakgrunden.
En annan fördel med Dapper och även DapperExtensions är att programmet styr skapandet av databasanslutningen. Detta hjälper dig att interagera med det elastiska databasklientbiblioteket som förmedlar databasanslutningar baserat på mappningen av shardletar till databaser.
Information om hur du hämtar Dapper-sammansättningarna finns i Dapper dot net(Dapper dot net). Information om Dapper-tillägg finns i DapperExtensions.
En snabb titt på klientbiblioteket för elastisk databas
Med klientbiblioteket för elastisk databas definierar du partitioner av dina programdata som kallas shardletar, mappar dem till databaser och identifierar dem genom att partitionera nycklar. Du kan ha så många databaser som du behöver och distribuera dina shardlets mellan dessa databaser. Mappningen av nyckelvärden för horisontell partitionering till databaserna lagras av en shardkarta som tillhandahålls av bibliotekets API:er. Den här funktionen kallas för hantering av fragmentkartor. Shard-kartan fungerar också som koordinator för databasanslutningar för begäranden som har en partitioneringsnyckel. Den här funktionen kallas för databeroende routning.
Karthanteraren för shard skyddar användare från inkonsekventa vyer till shardlet-data som kan inträffa när samtidiga shardlet-hanteringsåtgärder utförs i databaserna. För att göra det mappar shard databasanslutningarna för ett program som skapats med biblioteket. När shardhanteringsåtgärder kan påverka shardleten kan funktionen för shardkarta automatiskt avsluta en databasanslutning.
I stället för att använda det traditionella sättet att skapa anslutningar för Dapper måste du använda metoden Open Anslut ionForKey. Detta säkerställer att all validering sker och att anslutningar hanteras korrekt när data flyttas mellan shards.
Krav för Dapper-integrering
När du arbetar med både klientbiblioteket för elastiska databaser och Dapper-API:erna vill du behålla följande egenskaper:
- Skala ut: Vi vill lägga till eller ta bort databaser från datanivån för det fragmenterade programmet efter behov för programmets kapacitetskrav.
- Konsekvens: Eftersom programmet skalas ut med horisontell partitionering måste du utföra databeroende routning. Vi vill använda bibliotekets databeroende routningsfunktioner för att göra det. I synnerhet vill du behålla verifierings- och konsekvensgarantierna som tillhandahålls av anslutningar som asynkronas via shard map manager för att undvika skador eller fel frågeresultat. Detta säkerställer att anslutningar till en viss shardlet avvisas eller stoppas om (till exempel) shardleten för närvarande flyttas till en annan shard med hjälp av API:er för delning/sammanslagning.
- Objektmappning: Vi vill behålla bekvämligheten med de mappningar som tillhandahålls av Dapper för att översätta mellan klasser i programmet och de underliggande databasstrukturerna.
Följande avsnitt innehåller vägledning för dessa krav för program som baseras på Dapper och DapperExtensions.
Teknisk vägledning
Databeroende routning med Dapper
Med Dapper ansvarar programmet vanligtvis för att skapa och öppna anslutningarna till den underliggande databasen. Med en typ T av programmet returnerar Dapper frågeresultat som .NET-samlingar av typen T. Dapper utför mappningen från T-SQL-resultatraderna till objekt av typen T. På samma sätt mappar Dapper .NET-objekt till SQL-värden eller parametrar för DML-instruktioner (Data Manipulation Language). Dapper erbjuder den här funktionen via tilläggsmetoder på det vanliga Sql Anslut ion-objektet från ADO .NET SQL-klientbiblioteken. SQL-anslutningen som returneras av API:erna för elastisk skalning för DDR är också vanliga Sql Anslut ion-objekt. På så sätt kan vi direkt använda Dapper-tillägg över den typ som returneras av klientbibliotekets DDR-API, eftersom det också är en enkel SQL-klientanslutning.
Dessa observationer gör det enkelt att använda anslutningar som asynkronas av den elastiska databasens klientbibliotek för Dapper.
Det här kodexemplet (från det medföljande exemplet) illustrerar metoden där partitioneringsnyckeln tillhandahålls av programmet till biblioteket för att asynkrona anslutningen till rätt 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 }
);
}
Anropet till Api:et Open Anslut ionForKey ersätter standardskapandet och öppnandet av en SQL-klientanslutning. Open Anslut ionForKey-anropet tar de argument som krävs för databeroende routning:
- Fragmentkartan för åtkomst till de databeroende routningsgränssnitten
- Partitioneringsnyckeln för att identifiera shardleten
- Autentiseringsuppgifterna (användarnamn och lösenord) för att ansluta till fragmentet
Shard-mappningsobjektet skapar en anslutning till fragmentet som innehåller shardleten för den angivna partitioneringsnyckeln. Klient-API:erna för elastisk databas taggar också anslutningen för att implementera dess konsekvensgarantier. Eftersom anropet till Open Anslut ionForKey returnerar ett vanligt SQL-klientanslutningsobjekt följer det efterföljande anropet till metoden Kör tillägg från Dapper standardmetoden Dapper.
Frågor fungerar ungefär på samma sätt – du öppnar först anslutningen med open Anslut ionForKey från klient-API:et. Sedan använder du de vanliga Dapper-tilläggsmetoderna för att mappa resultatet av DIN SQL-fråga till .NET-objekt:
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);
}
}
Observera att användningsblocket med DDR-anslutningen omfattar alla databasåtgärder i blocket till den shard där tenantId1 behålls. Frågan returnerar endast bloggar som lagras på den aktuella fragmentet, men inte de som lagras på andra shards.
Databeroende routning med Dapper och DapperExtensions
Dapper levereras med ett ekosystem med ytterligare tillägg som kan ge ytterligare bekvämlighet och abstraktion från databasen när du utvecklar databasprogram. DapperExtensions är ett exempel.
Att använda DapperExtensions i programmet ändrar inte hur databasanslutningar skapas och hanteras. Det är fortfarande programmets ansvar att öppna anslutningar och vanliga SQL Client-anslutningsobjekt förväntas av tilläggsmetoderna. Vi kan förlita oss på Open Anslut ionForKey enligt beskrivningen ovan. Som följande kodexempel visar är den enda ändringen att du inte längre behöver skriva T-SQL-uttrycken:
using (SqlConnection sqlconn = shardingLayer.ShardMap.OpenConnectionForKey(
key: tenantId2,
connectionString: connStrBldr.ConnectionString,
options: ConnectionOptions.Validate))
{
var blog = new Blog { Name = name2 };
sqlconn.Insert(blog);
}
Och här är kodexemplet för frågan:
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);
}
}
Hantera tillfälliga fel
Microsoft Patterns &Practices-teamet publicerade programblocket för övergående felhantering för att hjälpa programutvecklare att minimera vanliga tillfälliga feltillstånd som uppstod när de kördes i molnet. Mer information finns i Perseverance, Secret of All Triumphs: Using the Transient Fault Handling Application Block (Tillfälliga programblock för felhantering).
Kodexemplet förlitar sig på det tillfälliga felbiblioteket för att skydda mot tillfälliga fel.
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 i koden ovan definieras som en SqlDatabaseTransientErrorDetectionStrategy med ett återförsöksantal på 10 och 5 sekunders väntetid mellan återförsök. Om du använder transaktioner kontrollerar du att omfånget för återförsök går tillbaka till början av transaktionen om det uppstår ett tillfälligt fel.
Begränsningar
De metoder som beskrivs i det här dokumentet medför ett par begränsningar:
- Exempelkoden för det här dokumentet visar inte hur du hanterar schema över shards.
- Med tanke på en begäran förutsätter vi att all databasbearbetning finns i en enda shard som identifieras av partitioneringsnyckeln som tillhandahålls av begäran. Det här antagandet gäller dock inte alltid, till exempel när det inte går att göra en horisontell partitioneringsnyckel tillgänglig. För att åtgärda detta innehåller klientbiblioteket för elastisk databas klassen MultiShardQuery. Klassen implementerar en anslutningsabstraktion för att fråga över flera shards. Att använda MultiShardQuery i kombination med Dapper ligger utanför omfånget för det här dokumentet.
Slutsats
Program som använder Dapper och DapperExtensions kan enkelt dra nytta av elastiska databasverktyg för Azure SQL Database. Genom de steg som beskrivs i det här dokumentet kan dessa program använda verktygets funktion för databeroende routning genom att ändra skapande och öppning av nya Sql Anslut ion-objekt för att använda Open Anslut ionForKey-anropet för det elastiska databasklientbiblioteket. Detta begränsar de programändringar som krävs till de platser där nya anslutningar skapas och öppnas.
Ytterligare resurser
Använder du inte elastiska databasverktyg än? Kolla in vår komma igång-guide. Om du har frågor kan du kontakta oss på microsofts Q&A-frågesida för SQL Database och för funktionsförfrågningar, lägga till nya idéer eller rösta på befintliga idéer i SQL Database-feedbackforumet.