Using Dapper with Oracle

c# dapper oracle

Question

We use Oracle as our database provider and have looked into replacing some of our data access layer (hard to maintain, harder to merge XSD's) with a saner repository based pattern using Dapper at the bottom layer. However, we have hit a number of issues when using it with oracle.

  • Named Parameters: these seem to be ignored, whenever they are used in a query Oracle seems to interpret them in any order it fancies. The SqlMapper returns correctly named parameters, they just aren't interpreted correctly in Oracle

  • The "@" naming convention for variables is incompatible with oracle named parameters. It expects to see ":" in front of any parameters

Has anybody previously encountered this and have any workarounds?

Accepted Answer

IMO, the correct approach here is not to (as per the accepted answer) use the database specific parameter prefix (so @ for sql-server, : for oracle) - but rather: use no prefix at all. So ultimately this is:

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

(etc)

In particular, a static property would be bad as it would limit you to one vendor per AppDomain.

Dapper has been updated with this change. It also now dynamically detects BindByName and sets it accordingly (all without needing a reference to OracleCommand).


Popular Answer

Resolution of the named parameter issue turned out to be because Oracle commands require the BindByName property set to true. To resolve this required a tweak to the SqlMapper itself. This is a bit nasty as the tweak isnt portable (it relies on a type check for a specific Oracle Command) but it works for our needs for the moment. The change involves updating the SetupCommand method, after creating the command form the connection object we type check and set the flag like so (~ln 635):

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

Finally to address the issue of the "@" to ":" problem in parameter names involved altering the CreateParamInfoGenerator method. I added a static string - DefaultParameterCharacter setting its value to ":" then modified ln 530 from:

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

to

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

and ln 546 from:

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

to:

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

This made dapper work flawlessly with Oracle commands




Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Is this KB legal? Yes, learn why