Токен зависимого параметра Dapper провайдера - PullRequest
0 голосов
/ 31 августа 2018

Есть ли способ написать параметризованный sql для разных провайдеров?

Пример:

connection.QuerySingle<string>("select name from user where id = :id", new {id = 4});

Это будет работать с провайдером оракула, но MsSql требует "@id" в качестве параметра.

Часто задаваемые вопросы о Dapper гласят:

Ваша задача - написать SQL-совместимый с вашим поставщиком базы данных.

Но как? В настоящее время у нас есть следующий обходной путь:

$".. where id = {db.ParamToken}id"

Но это действительно некрасиво писать в больших SQL.

Есть ли способ получить один токен для всех провайдеров?

1 Ответ

0 голосов
/ 05 сентября 2018

«Есть ли способ получить один токен для всех провайдеров?»

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

DbConnection connection = GetSomeConnection();
var infoTable = connection.GetSchema(DbMetaDataCollectionNames.DataSourceInformation);

В этой таблице будет одна строка с различной информацией о поставщике. Что касается именования параметров, будет столбец с именем ParameterMarkerPattern, представляющий строку шаблона Regex для проверки параметра. Если в этом столбце есть данные, первым символом будет ваш маркер DbParameter. Если столбец пуст, ParameterMarkerFormat может дать вам строковый формат, который будет применяться при построении имени вашего параметра.

«Но это действительно некрасиво писать в больших SQL».

На самом деле это не обойдется, если вы рассматриваете возможность прямого форматирования SQL, и ваш обходной путь уже намного проще, чем этот. Однако дополнительных данных, которые вы получаете от DataSourceInformation, должно быть достаточно для передачи собственной строки методу создания, который заменит начальный символ параметра по умолчанию (например, @) на соответствующий от поставщика. :

string sql = SqlIfy("SELECT name FROM user WHERE id = @id");

Вы можете пойти еще дальше и сделать то же самое для указанных в кавычках идентификаторов. Вы можете передать что-то вроде:

"SELECT [Name] FROM [dbo].[SomeTable]"

и получилось так, как

SELECT "Name" FROM "dbo"."SomeTable"

Все зависит от провайдера. Если вы хотите динамически создавать запросы на каком-либо пользовательском базовом классе провайдера, вы можете открыть исходное соединение и сохранить все данные, относящиеся к провайдеру. Вы не хотите звонить DbConnection.GetSchema каждый раз, когда используете соединение.

SQL Server: enter image description here

Oracle: enter image description here

...