Использование клиентской библиотеки эластичной базы данных с Dapper

Применимо к:База данных SQL Azure

Документ предназначен для разработчиков, которые используют Dapper для создания приложений, но также хотят применять инструменты эластичной базы данных, чтобы создавать приложения, реализующие сегментирование для горизонтального увеличения масштаба уровня данных. В документе показаны изменения, которые следует внести в приложениях на базе Dapper, для интеграции со средствами эластичной базы данных. Внимание уделяется совмещению методов управления сегментами эластичной базы данных и маршрутизации, зависящей от данных, с помощью Dapper.

Пример кода.Elastic DB Tools for Azure SQL - Dapper Integration (Средства эластичной базы данных для Базы данных SQL Azure — интеграция с Dapper).

Интеграция Dapper и DapperExtensions с клиентской библиотекой эластичной базы данных для Базы данных SQL Azure — это просто. Приложения могут использовать данные в зависимости от маршрутизации путем создания и открытия новых объектов SqlConnection, чтобы использовать вызов OpenConnectionForKey из клиентской библиотеки. Это ограничивает внесение изменений в приложении местами создания и открытия новых подключений.

Обзор Dapper

Dapper — это объектно-реляционный модуль сопоставления. Оно сопоставляет объекты .NET в приложении с объектами в реляционной базе данных (и наоборот). В первой части примера кода показано, как можно интегрировать клиентскую библиотеку эластичной базы данных с приложениями, созданными с помощью Dapper. Во второй части примера кода показано, как выполнить интеграцию при одновременном использовании Dapper и DapperExtensions.

Средство сопоставления в Dapper предоставляет методы расширения для подключений к базе данных, упрощающие отправку операторов T-SQL для выполнения базы данных или создания адресуемых ей запросов. Например, Dapper упрощает сопоставление объектов .NET и параметров операторов SQL для вызовов Execute и использование результатов SQL-запросов объектов .NET с помощью вызовов Query из Dapper.

При использовании DapperExtensions больше не требуется предоставлять операторы SQL. Методы расширения для подключений к базе данных, такие как GetList или Insert, создают инструкции SQL в фоновом режиме.

Другое преимущество использования Dapper и DapperExtensions заключается в том, что приложение контролирует создание подключения к базе данных. Это позволяет взаимодействовать с клиентской библиотекой эластичной базы данных, действующей в качестве посредника при подключении к базе данных, на основе сопоставления шардлетов с базами данных.

Сведения о получении сборок Dapper см. в статье Dapper dot net 1.50.2 (Dapper .NET 1.50.2). Сведения о расширениях Dapper см. в статье DapperExtensions 1.5.0.

Краткий обзор клиентской библиотеки эластичной базы данных

Клиентская библиотека эластичной базы данных позволяет определять разделы данных приложения, которые называются шардлетами, сопоставлять их с базами данных и определять с помощью ключей сегментирования. Вы можете использовать любое количество баз данных и распределять свои шардлеты между этими базами данных. Сопоставление значений ключа сегментирования с базами данных хранится картой сегментов, предоставляемой API библиотеки. Эта функция называется управление сопоставлением сегментов. Сопоставление сегментов также выступает в качестве посредника подключений к базе данных для запросов с ключом сегментирования. Эта функция называется маршрутизацией, зависящей от данных.

Shard maps and data-dependent routing

Диспетчер сопоставления сегментов защищает пользователей от получения несогласованных представлений данных шардлета, которые могут иметь место при выполнении параллельных операций управления шардлетом в базе данных. Для этого сопоставления сегментов опосредуют подключения к базе данных для приложения, созданного с помощью библиотеки. Так как операции управления сегментами могут повлиять на шардлет, функция сопоставления сегментов может завершать подключение к базе данных автоматически.

Вместо стандартных способов создания подключений для Dapper необходимо использовать метод OpenConnectionForKey. Это гарантирует, что при перемещении данных между сегментами выполняется полная проверка и надлежащее управление сегментами.

Требования к интеграции Dapper

Во время работы одновременно с клиентской библиотекой эластичной базы данных и интерфейсами API Dapper цель заключается в том, чтобы сохранить следующие свойства.

  • Горизонтальное увеличение масштаба. Необходимо добавлять базы данных в уровень данных сегментированного приложения и удалять их из него согласно потребностям приложения в ресурсах.
  • Согласованность. Так как приложение масштабируется путем сегментирования, необходимо выполнять маршрутизацию, зависящую от данных. Для этого понадобится использовать возможности маршрутизации, зависящей от данных. В частности, необходимо сохранить гарантии проверки и согласованности, предоставляемые с помощью подключений, которые проходят через диспетчер сопоставления сегментов, во избежание повреждения или получения неправильных результатов запросов. Это гарантирует, что подключения к заданному шардлету отклоняются или останавливаются, если (например) в настоящее время шардлет перемещается в другой сегмент с помощью API для разделения и объединения.
  • Сопоставление объектов.Необходимо сохранить удобство сопоставлений, предоставляемое Dapper, для преобразования между классами в приложении и базовыми структурами базы данных.

В следующем разделе приведены рекомендации по этим требованиям для приложений, созданных с помощью Dapper и DapperExtensions.

Техническое руководство

Маршрутизация, зависящая от данных, с помощью Dapper

При использовании Dapper приложение, как правило, отвечает за создание и открытие подключений к базе данных. Если присвоить приложению тип T, Dapper возвращает результаты запроса в качестве коллекции .NET типа T. Dapper сопоставляет данные в строках результатов T-SQL с объектами типа T. Аналогичным образом Dapper сопоставляет объекты .NET в значениях или параметрах SQL для операторов языка обработки данных (DML). Dapper обеспечивает эти функциональные возможности с помощью методов расширения в регулярном объекте SqlConnection из библиотек ADO.NET для клиента SQL. Подключения SQL, возвращенные API-интерфейсами эластичного масштабирования для DDR, также являются регулярными объектами SqlConnection. Это позволяет напрямую использовать расширения Dapper по типу, возвращаемого API DDR клиентской библиотеки, так как это также простое подключение клиента SQL.

Эти наблюдения упрощают использование подключений, которые проходят через клиентскую библиотеку эластичной базы данных для Dapper.

В этом примере кода (из соответствующего примера) показан подход, в котором приложение предоставляет ключ сегментирования библиотеке, чтобы подключение прошло через посредника к правильному сегменту.

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

Чтобы вызвать OpenConnectionForKey , API-интерфейс заменяет создание и открытие подключения клиента SQL по умолчанию. Метод OpenConnectionForKey при вызове принимает аргументы, которые требуются для маршрутизации, зависящей от данных.

  • сопоставление сегментов для доступа к интерфейсам маршрутизации, зависящей от данных;
  • ключ сегментирования для определения шардлета;
  • учетные данные (имя пользователя и пароль) для подключения к сегменту.

Объект сопоставления сегментов создает открытое подключение к сегменту, в котором содержится шардлет, соответствующий заданному ключу сегментирования. Клиентские API-интерфейсы эластичной базы данных также помечают подключение тегом для реализации гарантий согласованности. Так как при вызове OpenConnectionForKey возвращается регулярный объект подключения клиента SQL, последующий вызов метода расширения Execute из Dapper выполняется по стандартной схеме.

Запросы формируются в целом одинаково: сначала открывается подключение с помощью OpenConnectionForKey из клиентского API-интерфейса, а затем используются регулярные методы расширения Dapper для сопоставления результатов SQL-запроса в объектах .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);
            }
    }

Обратите внимание, что блок using с подключением DDR ограничивает все операции базы данных в пределах блока к одному сегменту, в котором хранится tenantId1. Запрос возвращает только блоги, хранящиеся в текущем сегменте, а не в любых других сегментах.

Маршрутизация, зависящая от данных, с использованием Dapper и DapperExtensions

В Dapper включена экосистема дополнительных расширений, которые могут обеспечивать дополнительное удобство и предоставлять абстракцию из базы данных при разработке приложений баз данных. И примером таких расширений является DapperExtensions.

При использовании DapperExtensions в приложении способ создания подключений к базе данных и управления ими не меняется. Это по-прежнему ответственность приложения за открытие подключений, и обычные объекты подключения клиента SQL ожидаются методами расширения. Мы можем использовать OpenConnectionForKey , как описано выше. Единственное изменение заключается в том, что больше не нужно писать операторы 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);
    }

А вот пример кода для запроса:

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

Обработка временных сбоев

Команда Microsoft Patterns & Practices опубликовала блок приложений обработки временных сбоев, чтобы позволить разработчикам приложений устранять распространенные временные сбои при выполнении в облаке. Дополнительные сведения см. в статье 4 - Perseverance, Secret of All Triumphs: Using the Transient Fault Handling Application Block (4. Настойчивость — секрет всех побед. Использование блока приложения для обработки временных ошибок).

В примере кода для защиты от временных сбоев используется библиотека временных сбоев.

    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 в приведенном выше коде определена как SqlDatabaseTransientErrorDetectionStrategy с числом попыток, равным 10, и 5-секундным временем ожидания между повторами попытки. При использовании транзакций убедитесь, что при возникновении временного сбоя область повтора переходит к началу транзакции.

Ограничения

Подходы, описанные в данном документе, имеют несколько ограничений:

  • В примере кода для этого документа не показано, как управлять схемой для разных сегментов.
  • Предполагается, что вся обработка в базе данных для выполнения запроса ведется в пределах одного сегмента, который идентифицируется ключом сегментирования, предоставленном в запросе. Тем не менее, это не всегда так, например, в случае, если невозможно сделать ключ сегментирования доступным. Для решения этой проблемы клиентская библиотека эластичной базы данных включает класс MultiShardQuery. Этот класс реализует абстракцию подключения для выполнения запросов нескольких сегментов. Использование MultiShardQuery вместе с EF выходит за рамки данного документа

Заключение

Приложения, использующие Dapper и DapperExtensions, могут легко использовать преимущества средств эластичной базы данных SQL Azure. С помощью шагов, описанных в этом документе, приложения могут использовать возможности инструмента для маршрутизации, зависящей от данных. Для этого требуется изменить создание и открытие новых объектов SqlConnection, чтобы использовать вызов OpenConnectionForKey клиентской библиотеки эластичной базы данных. Это ограничивает внесение требуемых изменений в приложении местами создания и открытия новых подключений.

Дополнительные ресурсы

Еще не используете средства эластичных баз данных? Ознакомьтесь с нашим руководством по началу работы. Возникшие вопросы вы можете задать нам на странице вопросов Microsoft Q&A по Базе данных SQL. Что касается запросов новых функций, вы можете поделиться новыми идеями или проголосовать за существующие на форуме отзывов по Базе данных SQL.