将Dapper与Oracle结合使用

Wol*_*yrd 12 c# oracle dapper

我们使用Oracle作为我们的数据库提供者,并且已经考虑使用底层的Dapper替换我们的一些数据访问层(难以维护,难以合并XSD)和基于存储库的模式.但是,在与oracle一起使用时,我们遇到了许多问题.

  • 命名参数:这些似乎被忽略,无论何时在查询中使用它,Oracle似乎都会以它所想的任何顺序来解释它们.SqlMapper返回正确命名的参数,它们在Oracle中无法正确解释

  • 变量的"@"命名约定与oracle命名参数不兼容.它希望在任何参数前面看到":"

有没有人以前遇到这个并有任何解决方法?

Mar*_*ell 14

IMO,这里的正确的做法是以(按照公认的答案)使用数据库特定的参数前缀(这样@的SQL服务器,:用于Oracle) -而是:使用无前缀可言.所以最终这是:

il.Emit(OpCodes.Ldstr, prop.Name);
Run Code Online (Sandbox Code Playgroud)

(等等)

特别是,一个static属性会很糟糕,因为它会限制你每个供应商AppDomain.

Dapper已更新此更改.它现在也可以相应地动态检测BindByName和设置它(所有这些都不需要引用OracleCommand).


Wol*_*yrd 6

已解决命名参数问题的原因是Oracle命令要求将BindByName属性设置为true.要解决此问题,需要对SqlMapper本身进行调整.由于调整不是可移植的(它依赖于特定Oracle命令的类型检查),这有点令人讨厌,但它适用于我们当前的需求.更改涉及更新SetupCommand方法,在创建命令后,我们键入检查连接对象并设置标志,如此(~ln 635):

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

最后解决参数名称中"@"到":"问题涉及改变CreateParamInfoGenerator方法的问题.我添加了一个静态字符串 - DefaultParameterCharacter将其值设置为":"然后修改ln 530:

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

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

和来自:

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

至:

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

这使得dapper在Oracle命令下完美运行