13

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

  • 命名参数:这些似乎被忽略了,每当它们在查询中使用时,Oracle 似乎会以它喜欢的任何顺序解释它们。SqlMapper 返回正确命名的参数,它们只是在 Oracle 中没有正确解释

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

有没有人以前遇到过这种情况并有任何解决方法?

4

2 回答 2

15

IMO,这里的正确方法不是(根据公认的答案)使用数据库特定的参数前缀(@对于 sql-server,:对于 oracle)-而是:根本不使用前缀。所以最终这是:

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

(ETC)

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

Dapper 已根据此更改进行了更新。它现在还可以动态检测BindByName并相应地设置它(所有这些都不需要对 的引用OracleCommand)。

于 2011-06-06T12:21:21.777 回答
6

命名参数问题的解决原来是因为 Oracle 命令要求将 BindByName 属性设置为 true。要解决这个问题,需要对 SqlMapper 本身进行调整。这有点讨厌,因为调整不是可移植的(它依赖于特定 Oracle 命令的类型检查),但它目前可以满足我们的需求。更改涉及更新 SetupCommand 方法,在从连接对象创建命令后,我们键入检查并设置标志,如下所示(~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)

和 ln 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)

这使得 Dapper 可以完美地使用 Oracle 命令

于 2011-06-02T10:06:03.360 回答