C# 在Oracle中使用Dapper

C# 在Oracle中使用Dapper,c#,oracle,dapper,C#,Oracle,Dapper,我们使用Oracle作为我们的数据库提供商,并已考虑将我们的一些数据访问层(难以维护,难以合并XSD)替换为在底层使用Dapper的更为明智的基于存储库的模式。但是,在与oracle一起使用时,我们遇到了一些问题 命名参数:无论何时在查询中使用这些参数,Oracle似乎都会按照自己喜欢的顺序来解释它们。SqlMapper返回正确命名的参数,只是在Oracle中没有正确解释这些参数 变量的“@”命名约定与oracle命名参数不兼容。它希望在任何参数前面看到“:” 以前是否有人遇到过这种情况,并

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

  • 命名参数:无论何时在查询中使用这些参数,Oracle似乎都会按照自己喜欢的顺序来解释它们。SqlMapper返回正确命名的参数,只是在Oracle中没有正确解释这些参数

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


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

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

最后,要解决“@”to“:”的问题,参数名中的问题涉及更改CreateParamInfoGenerator方法。我添加了一个静态字符串-DefaultParameterCharacter,将其值设置为“:”,然后将LN530修改为:

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

和ln 546,来自:

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


这使得dapper能够完美地使用Oracle命令,在IMO中,正确的方法不是(根据公认的答案)使用特定于数据库的参数前缀(因此对于sql server,
@
,对于Oracle,
),而是:完全不使用前缀。因此,最终这是:

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

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


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

哎哟。。。真是个好主意。。。我不介意把这件事做得干净利落,只要不会造成依赖性。。。也。。。oracle中的存储过程是什么?好问题,现在还不必对其中一个进行调整。今天下午我将尝试一个,并将我的发现发布到这里;var bindByName=cmd.GetType().GetProperties().Where(propertyInfo=>propertyInfo.Name==“bindByName”).FirstOrDefault(null);如果(bindByName!=null){bindByName.SetValue(cmd,true,null);}(我们对命令进行反思,看看它是否具有bindByName属性,然后设置它,如果它具有,这在SetupCommand方法中进行)实际上,我们必须在那里烘焙一个动态方法以保持它的快速运行一个存储过程。使用相同的更改运行良好。这是否意味着,我可以将dapper与oracle一起使用,而无需修改?@Benny这就是我的想法,是的,我仍然感到困惑,不使用特定于数据库的参数前缀是什么意思,你能举个例子吗?thanks@Benny不,因为示例在代码中,您从未见过。您的查询必须包含前缀。“无前缀”是cmd.Parameters.Add(…)中发生的情况-Add(@foo”)与Add(“foo”)之间的区别。后者更正确。我现在明白了,所以no前缀只在使用cmd.Parameters.Add()时有效。如果在直接查询sql命令中,例如“select*from foo where col=@foo1”,我仍然必须使用参数前缀,但这意味着sql查询命令绑定到特定的数据库提供程序,“@”表示sql server,“:”表示oracle,sql命令不表示trans db,:(
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)
il.Emit(OpCodes.Ldstr, prop.Name);