Usando Dapper con Oracle

c# dapper oracle

Pregunta

Usamos Oracle como nuestro proveedor de bases de datos y hemos buscado reemplazar parte de nuestra capa de acceso a datos (difícil de mantener, más difícil de combinar XSD) con un patrón basado en un repositorio más seguro usando Dapper en la capa inferior. Sin embargo, hemos atacado una serie de problemas al usarlo con Oracle.

  • Parámetros con nombre: estos parecen ignorados, cada vez que se utilizan en una consulta, Oracle parece interpretarlos en el orden que desee. El SqlMapper devuelve los parámetros correctamente nombrados, simplemente no se interpretan correctamente en Oracle

  • La convención de nomenclatura "@" para variables no es compatible con los parámetros nombrados de Oracle. Espera ver ":" delante de cualquier parámetro

¿Alguien ha encontrado esto anteriormente y tiene alguna solución alternativa?

Respuesta aceptada

La OMI, el enfoque correcto aquí no es (según la respuesta aceptada) utilizar el parámetro específico prefijo de la base de datos (por lo @ para SQL-servidor, : por Oracle) -, sino más bien: utilizar ningún prefijo en absoluto. Entonces, en última instancia, esto es:

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

(etc.)

En particular, una propiedad static sería mala, ya que lo limitaría a un proveedor por AppDomain .

Dapper ha sido actualizado con este cambio. Ahora también detecta dinámicamente BindByName y lo configura en consecuencia (todo sin necesitar una referencia a OracleCommand ).


Respuesta popular

La resolución del problema del parámetro nombrado resultó ser porque los comandos de Oracle requieren que la propiedad BindByName se establezca en verdadero. Para resolver esto, se requirió un ajuste al SqlMapper. Esto es un poco desagradable ya que el ajuste no es portátil (se basa en una verificación de tipo para un comando específico de Oracle) pero funciona para nuestras necesidades por el momento. El cambio implica la actualización del método SetupCommand, después de crear el comando desde el objeto de conexión, escribimos check y establecemos el flag como tal (~ ln 635):

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

Por último, para abordar el problema del "@" al ":" problema en los nombres de los parámetros implica la alteración del método CreateParamInfoGenerator. Agregué una cadena estática - DefaultParameterCharacter estableciendo su valor a ":" y luego modifiqué ln 530 desde:

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

a

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

y en 546 de:

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

a:

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

Esto hizo que Dapper funcione sin problemas con los comandos de Oracle



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
¿Es esto KB legal? Sí, aprende por qué