Использование Dapper с Oracle - PullRequest
12 голосов
/ 02 июня 2011

Мы используем Oracle в качестве нашего поставщика базы данных и изучаем возможность замены некоторых из наших уровней доступа к данным (сложно поддерживать, сложнее объединить XSD) на более рациональный шаблон на основе хранилища с использованием Dapper на нижнем уровне. Тем не менее, мы столкнулись с рядом проблем при использовании с оракулом.

  • Именованные параметры: они, похоже, игнорируются, когда бы они ни использовались в запросе, Oracle, кажется, интерпретирует их в любом порядке, который он себе представляет. SqlMapper возвращает правильно названные параметры, они просто неправильно интерпретируются в Oracle

  • Соглашение о присвоении имен "@" несовместимо с параметрами, названными оракулом. Он ожидает увидеть «:» перед любыми параметрами

Кто-нибудь ранее сталкивался с этим и есть какие-то обходные пути?

Ответы [ 2 ]

14 голосов
/ 06 июня 2011

IMO, правильный подход здесь , а не , чтобы (согласно принятому ответу) использовать префикс параметра базы данных (таким образом @ для sql-сервера, : для оракула) - а точнее: вообще не используйте префикс . Итак, в конечном итоге это:

il.Emit(OpCodes.Ldstr, prop.Name);

(и т.д.)

В частности, свойство static было бы плохим, так как оно ограничивало бы вас одним поставщиком на AppDomain.

Dapper был обновлен с этим изменением. Теперь он также динамически обнаруживает BindByName и устанавливает его соответствующим образом (все без ссылки на OracleCommand).

6 голосов
/ 02 июня 2011

Решение проблемы с именованным параметром оказалось из-за того, что для команд Oracle для свойства BindByName установлено значение true. Для решения этой проблемы потребовалась настройка самого SqlMapper. Это немного неприятно, так как твик не переносим (он полагается на проверку типа для определенной команды Oracle), но на данный момент он работает для наших нужд. Это изменение включает обновление метода SetupCommand, после создания команды из объекта подключения мы печатаем команду check и устанавливаем флаг следующим образом (~ ln 635):

var cmd = cnn.CreateCommand();
if (cmd is OracleCommand)
{
    ((OracleCommand)cmd).BindByName = true; // Oracle Command Only
}

Наконец, для решения проблемы «@» в «:» в именах параметров необходимо изменить метод CreateParamInfoGenerator. Я добавил статическую строку - DefaultParameterCharacter, установив ее значение в ":", затем изменил ln 530 из:

il.Emit(OpCodes.Ldstr, "@" + prop.Name); // stack is now [parameters] [c

до

il.Emit(OpCodes.Ldstr, DefaultParameterCharacter + prop.Name); // stack is now [parameters] [command] [name] (Changed @ to : for oracle)

и № 546 от:

il.Emit(OpCodes.Ldstr, "@" + prop.Name); // stack is now [parameters] [parameters] [parameter] [parameter] [name] (Changed @ to : for oracle)

до:

il.Emit(OpCodes.Ldstr, DefaultParameterCharacter + prop.Name); // stack is now [parameters] [parameters] [parameter] [parameter] [name] (Changed @ to : for oracle)

Это позволило безупречно работать командам Oracle

...