Używanie elastycznej biblioteki klienta bazy danych z narzędziem Dapper

Dotyczy:Azure SQL Database

Ten dokument jest przeznaczony dla deweloperów korzystających z narzędzia Dapper do tworzenia aplikacji, ale także chce objąć elastyczne narzędzia bazy danych, aby tworzyć aplikacje implementujące fragmentowanie w celu skalowania w poziomie warstwy danych. W tym dokumencie przedstawiono zmiany w aplikacjach opartych na programie Dapper, które są niezbędne do integracji z elastycznymi narzędziami bazy danych. Koncentrujemy się na komponowaniu elastycznego zarządzania fragmentami bazy danych i routingu zależnego od danych za pomocą narzędzia Dapper.

Przykładowy kod: elastyczne narzędzia bazy danych na potrzeby integracji z usługą Azure SQL Database — Dapper.

Integrowanie rozszerzeń dapper i DapperExtensions z elastyczną biblioteką klienta bazy danych dla usługi Azure SQL Database jest łatwe. Aplikacje mogą używać routingu zależnego od danych, zmieniając tworzenie i otwieranie nowych obiektów sql Połączenie ion w celu użycia wywołania Open Połączenie ionForKey z biblioteki klienta. Ogranicza to zmiany w aplikacji tylko w przypadku tworzenia i otwierania nowych połączeń.

Omówienie narzędzia Dapper

Dapper to maper obiektowo-relacyjny. Mapuje obiekty platformy .NET z aplikacji na relacyjną bazę danych (i odwrotnie). Pierwsza część przykładowego kodu ilustruje sposób integrowania elastycznej biblioteki klienta bazy danych z aplikacjami opartymi na języku Dapper. Druga część przykładowego kodu ilustruje sposób integracji zarówno w przypadku korzystania z języka Dapper, jak i dapperExtensions.

Funkcja mapowania w narzędziu Dapper udostępnia metody rozszerzeń na połączeniach bazy danych, które upraszczają przesyłanie instrukcji języka T-SQL do wykonywania lub wykonywania zapytań dotyczących bazy danych. Na przykład narzędzie Dapper ułatwia mapowania między obiektami platformy .NET a parametrami instrukcji SQL dla wywołań Execute lub użycie wyników zapytań SQL do obiektów platformy .NET przy użyciu wywołań zapytań zapytań z języka Dapper.

W przypadku korzystania z rozszerzenia DapperExtensions nie trzeba już podawać instrukcji SQL. Metody rozszerzeń, takie jak GetList lub Insert za pośrednictwem połączenia bazy danych, tworzą instrukcje SQL w tle.

Kolejną zaletą narzędzia Dapper, a także dapperExtensions jest to, że aplikacja kontroluje tworzenie połączenia z bazą danych. Ułatwia to interakcję z elastyczną biblioteką klienta bazy danych, która brokeruje połączenia bazy danych na podstawie mapowania fragmentów do baz danych.

Aby uzyskać zestawy Dapper, zobacz Dapper dot net. Aby zapoznać się z rozszerzeniami języka Dapper, zobacz DapperExtensions.

Krótki przegląd elastycznej biblioteki klienta bazy danych

Korzystając z elastycznej biblioteki klienta bazy danych, zdefiniujesz partycje danych aplikacji o nazwie shardlets, zamapuj je na bazy danych i zidentyfikuj je przez klucze fragmentowania. Możesz mieć dowolną liczbę baz danych i dystrybuować fragmenty w tych bazach danych. Mapowanie wartości klucza fragmentowania do baz danych jest przechowywane przez mapę fragmentów dostarczaną przez interfejsy API biblioteki. Ta funkcja jest nazywana zarządzanie mapami fragmentów. Mapa fragmentów służy również jako broker połączeń bazy danych dla żądań, które mają klucz fragmentowania. Ta funkcja jest określana jako routing zależny od danych.

Shard maps and data-dependent routing

Menedżer mapy fragmentów chroni użytkowników przed niespójnymi widokami w dane fragmentów, które mogą wystąpić, gdy w bazach danych są wykonywane współbieżne operacje zarządzania fragmentami. W tym celu fragment mapuje brokera połączeń bazy danych dla aplikacji utworzonej za pomocą biblioteki. Gdy operacje zarządzania fragmentami mogą mieć wpływ na podfragment, umożliwia to automatyczne zabicie połączenia z bazą danych przez funkcję mapy fragmentów.

Zamiast używać tradycyjnego sposobu tworzenia połączeń dla języka Dapper, należy użyć metody Open Połączenie ionForKey. Dzięki temu wszystkie operacje weryfikacji są prawidłowo zarządzane, gdy wszystkie dane są przemieszczane między fragmentami.

Wymagania dotyczące integracji narzędzia Dapper

Podczas pracy z biblioteką klienta elastycznej bazy danych i interfejsami API programu Dapper należy zachować następujące właściwości:

  • Skalowanie w poziomie: chcemy dodawać lub usuwać bazy danych z warstwy danych aplikacji podzielonej na fragmenty zgodnie z potrzebami dotyczącymi pojemności aplikacji.
  • Spójność: ponieważ aplikacja jest skalowana w poziomie przy użyciu fragmentowania, należy przeprowadzić routing zależny od danych. W tym celu chcemy użyć funkcji routingu zależnego od danych biblioteki. W szczególności chcesz zachować gwarancje walidacji i spójności zapewniane przez połączenia obsługiwane przez menedżera mapy fragmentów, aby uniknąć uszkodzenia lub nieprawidłowych wyników zapytania. Dzięki temu połączenia z danym podfragmentem zostaną odrzucone lub zatrzymane, jeśli (na przykład) fragment jest obecnie przenoszony do innego fragmentu przy użyciu interfejsów API podziału/scalania.
  • Mapowanie obiektów: chcemy zachować wygodę mapowań udostępnianych przez program Dapper w celu tłumaczenia między klasami w aplikacji a bazowymi strukturami baz danych.

Poniższa sekcja zawiera wskazówki dotyczące tych wymagań dotyczących aplikacji opartych na rozszerzeniach Dapper i DapperExtensions.

Wskazówki techniczne

Routing zależny od danych za pomocą narzędzia Dapper

W przypadku języka Dapper aplikacja jest zwykle odpowiedzialna za tworzenie i otwieranie połączeń z bazową bazą danych. Biorąc pod uwagę typ T przez aplikację, narzędzie Dapper zwraca wyniki zapytania jako kolekcje platformy .NET typu T. Dapper wykonuje mapowanie z wierszy wyników języka T-SQL do obiektów typu T. Podobnie język Dapper mapuje obiekty platformy .NET na wartości SQL lub parametry instrukcji języka manipulowania danymi (DML). Program Dapper oferuje tę funkcję za pośrednictwem metod rozszerzeń w zwykłym obiekcie Sql Połączenie ion z bibliotek klienta SQL ADO .NET. Połączenie SQL zwracane przez interfejsy API elastycznej skali dla pamięci DDR są również zwykłymi obiektami Sql Połączenie ion. Dzięki temu można bezpośrednio używać rozszerzeń języka Dapper przez typ zwracany przez interfejs API DDR biblioteki klienta, ponieważ jest to również proste połączenie klienta SQL.

Te obserwacje ułatwiają korzystanie z połączeń obsługiwanych przez elastyczną bibliotekę klienta bazy danych dla języka Dapper.

Ten przykład kodu (z towarzyszącego przykładu) ilustruje podejście, w którym klucz fragmentowania jest udostępniany przez aplikację do biblioteki w celu brokera połączenia z odpowiednim fragmentem.

    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 }
                        );
    }

Wywołanie interfejsu API Open Połączenie ionForKey zastępuje domyślne tworzenie i otwieranie połączenia klienta SQL. Wywołanie Open Połączenie ionForKey przyjmuje argumenty wymagane do routingu zależnego od danych:

  • Mapa fragmentów w celu uzyskania dostępu do interfejsów routingu zależnego od danych
  • Klucz fragmentowania w celu zidentyfikowania fragmentu
  • Poświadczenia (nazwa użytkownika i hasło) umożliwiające nawiązanie połączenia z fragmentem

Obiekt mapy fragmentu tworzy połączenie z fragmentem zawierającym fragment dla danego klucza fragmentowania. Interfejsy API klienta elastycznej bazy danych również tagują połączenie w celu zaimplementowania gwarancji spójności. Ponieważ wywołanie metody Open Połączenie ionForKey zwraca zwykły obiekt połączenia klienta SQL, kolejne wywołanie metody rozszerzenia Execute z narzędzia Dapper jest zgodne ze standardową praktyką języka Dapper.

Zapytania działają bardzo podobnie — najpierw otwierasz połączenie przy użyciu interfejsu API klienta Open Połączenie ionForKey. Następnie używasz zwykłych metod rozszerzenia Dapper do mapowania wyników zapytania SQL na obiekty platformy .NET:

    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);
            }
    }

Należy pamiętać, że blok using z połączeniem DDR zawiera wszystkie operacje bazy danych w bloku do jednego fragmentu, w którym jest przechowywany identyfikator tenantId1. Zapytanie zwraca tylko blogi przechowywane w bieżącym fragmentze, ale nie te przechowywane na innych fragmentach.

Routing zależny od danych z rozszerzeniami Dapper i DapperExtensions

Narzędzie Dapper oferuje ekosystem dodatkowych rozszerzeń, które mogą zapewnić dalszą wygodę i abstrakcję z bazy danych podczas tworzenia aplikacji baz danych. Przykładowe rozszerzenia dapperExtensions.

Używanie rozszerzeń dapperExtensions w aplikacji nie zmienia sposobu tworzenia i zarządzania połączeniami bazy danych. Nadal jest to odpowiedzialność aplikacji za otwieranie połączeń, a regularne obiekty połączenia klienta SQL są oczekiwane przez metody rozszerzeń. Możemy polegać na open Połączenie ionForKey, jak opisano powyżej. Jak pokazują poniższe przykłady kodu, jedyną zmianą jest to, że nie trzeba już pisać instrukcji języka T-SQL:

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

Oto przykładowy kod dla zapytania:

    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);
           }
    }

Obsługa błędów przejściowych

Zespół ds. wzorców i rozwiązań firmy Microsoft opublikował blok aplikacji obsługi błędów przejściowych, aby pomóc deweloperom aplikacji w ograniczeniu typowych przejściowych warunków błędów napotkanych podczas uruchamiania w chmurze. Aby uzyskać więcej informacji, zobacz Perseverance, Secret of All Triumphs: Using the Transient Fault Handling Application Block (Sekret wszystkich triumfów: używanie przejściowego bloku aplikacji do obsługi błędów).

Przykładowy kod opiera się na bibliotece błędów przejściowych w celu ochrony przed błędami przejściowymi.

    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 w powyższym kodzie jest definiowany jako sqlDatabaseTransientErrorDetectionStrategy z liczbą ponownych prób wynoszącą 10 i 5 sekund oczekiwania między ponownymi próbami. Jeśli używasz transakcji, upewnij się, że zakres ponawiania prób powróci do początku transakcji w przypadku błędu przejściowego.

Ograniczenia

Podejścia opisane w tym dokumencie wiążą się z kilkoma ograniczeniami:

  • Przykładowy kod tego dokumentu nie pokazuje, jak zarządzać schematem między fragmentami.
  • Biorąc pod uwagę żądanie, przyjęto założenie, że wszystkie jej przetwarzanie bazy danych znajduje się w jednym fragmentze zidentyfikowanym przez klucz fragmentowania dostarczony przez żądanie. Jednak to założenie nie zawsze jest przechowywane, na przykład wtedy, gdy nie jest możliwe udostępnienie klucza fragmentowania. Aby rozwiązać ten problem, biblioteka klienta elastycznej bazy danych zawiera klasę MultiShardQuery. Klasa implementuje abstrakcję połączenia na potrzeby wykonywania zapytań względem kilku fragmentów. Używanie trybu MultiShardQuery w połączeniu z narzędziem Dapper wykracza poza zakres tego dokumentu.

Podsumowanie

Aplikacje korzystające z narzędzi Dapper i DapperExtensions mogą łatwo korzystać z elastycznych narzędzi bazy danych dla usługi Azure SQL Database. W ramach kroków opisanych w tym dokumencie te aplikacje mogą używać funkcji narzędzia do routingu zależnego od danych, zmieniając tworzenie i otwieranie nowych obiektów Sql Połączenie ion w celu użycia wywołania Open Połączenie ionForKey elastycznej biblioteki klienta bazy danych. Ogranicza to zmiany aplikacji wymagane do tych miejsc, w których tworzone i otwierane są nowe połączenia.

Dodatkowe zasoby

Jeszcze nie korzystasz z narzędzi elastycznych baz danych? Zapoznaj się z naszym przewodnikiem Wprowadzenie. W przypadku pytań skontaktuj się z nami na stronie pytań i odpowiedzi dotyczących usługi SQL Database oraz w przypadku żądań funkcji, dodaj nowe pomysły lub zagłosuj na istniejące pomysły na forum opinii usługi SQL Database.