【发布时间】:2013-11-04 11:40:03
【问题描述】:
在我的例子中,为什么命名或位置查询参数不适用于 NHibernate?
认为以下陈述是正确的:
在 Oracle 数据库 X 和 Y 版本 11.2.0.3.0 上,存在“MyRole”角色 由“MyPassword”标识并授予我连接的用户 作为。
这是一些代码:
public void SetRole(string roleName, string rolePassword)
{
if (HasRoleBeenSet) return;
try
{
session.CreateSQLQuery("SET ROLE ? IDENTIFIED BY ?")
.SetString(0, roleName)
.SetString(1, rolePassword)
.ExecuteUpdate();
HasRoleBeenSet = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
SetRole("MyRole", "MyPassword");
抛出以下异常:
NHibernate.Exceptions.GenericADOException: 无法执行本机批量操作查询:SET ROLE?由 ? [SQL: 设置角色:p0 由:p1 识别] ---> System.Data.OracleClient.OracleException: ORA-01937: 角色名称丢失或无效
当我使用 Toad 套件中包含的 SQLMonitor 时,发送到数据库的 SQL 看起来像这样 SET ROLE ? IDENTIFIED BY ?,错误 Error occurred: [1937] (ORA-01937: missing or invalid role name) 显示在下面。
当我查看 FNH 自己生成的带有参数的查询时,它们看起来像这样:
SchemaName.errorHandler.logError(:v0);
:1=['The error message']
但当我使用 CreateSQLQuery() 手动创建查询时,情况并非如此
好的,下一个代码示例是这样的:
...
session.CreateSQLQuery("SET ROLE :roleName IDENTIFIED BY :rolePassword")
.SetString("roleName", roleName)
.SetString("rolePassword", rolePassword)
.ExecuteUpdate();
...
输出如下错误(相同的错误):
NHibernate.Exceptions.GenericADOException: 无法执行本机批量操作查询:SET ROLE :roleName IDENTIFIED BY :rolePassword [SQL: 设置角色:p0 由:p1 识别] ---> System.Data.OracleClient.OracleException: ORA-01937: 角色名称丢失或无效
第三个代码示例:
...
session.CreateSQLQuery(string.Format("SET ROLE {0} IDENTIFIED BY {1}",
roleName,
rolePassword))
.ExecuteUpdate();
...
在 Oracle 数据库 X 上,这很有效,在 Oracle 数据库 Y 上,这不能很好地工作并给我这个错误:
NHibernate.Exceptions.GenericADOException: 无法执行本机批量操作查询:SET ROLE MyRole IDENTIFIED BY MyPassword [SQL: SET ROLE MyRole IDENTIFIED BY MyPassword] ---> System.Data.OracleClient.OracleException: ORA-00933: SQL 命令未正确结束
我尝试在语句末尾添加一个分号 ;,但这会导致 invalid character 错误。
如果我像这样在密码周围添加双引号,它突然也适用于 Oracle 数据库 Y
...
session.CreateSQLQuery(string.Format("SET ROLE {0} IDENTIFIED BY \"{1}\"",
roleName,
rolePassword))
.ExecuteUpdate();
...
问题是这不是一个很好的解决方案,因为 FNH 现在会在记录的异常中溢出密码。我不知道这里有什么问题,这里没有明确的问题,因为我不知道该问什么,然后尖叫寻求帮助,希望有人能对此有所了解。
在 cmets 中进行了一些讨论后,我尝试了以下方法:
...
session.CreateSQLQuery(string.Format("SET ROLE {0} IDENTIFIED BY :rolePassword",
roleName))
.SetString("rolePassword", rolePassword)
.ExecuteUpdate();
...
我尝试了 :named 和 ? (位置)参数,带单引号、双引号,似乎什么都做不了。
这段代码抛出著名的ORA-00933: SQL command not properly ended 错误
【问题讨论】:
-
我猜密码可以作为参数,而角色名不能(比如尝试将表名作为 FROM 子句的参数传递)。解决方案应该是您的第一次和最后一次尝试的混合(角色名称为 String.Format,密码为参数)另外,也许存在另一种 oracle 语法允许将角色名称作为字符串传递。
-
这听起来像是解决方案,或者至少是其中的一部分,我试过了,现在我得到了
SQL command not properly ended错误,我尝试在查询中添加双引号,同样的错误,尝试在周围添加双引号密码,同样的错误。 -
试过这个吗?
session.CreateSQLQuery(string.Format("SET ROLE {0} IDENTIFIED BY ?",roleName)) .SetString(0, rolePassword) .ExecuteUpdate(); -
对命名参数和位置参数进行了同样的尝试
-
尝试创建一个不使用 NHibernate 的更简单的测试 - 只是一个普通的旧 ADO.NET 参数化
DbCommand。这将在您诊断问题时消除一些未知因素。一旦你弄清楚如何让 Oracle 和 ADO.NET 一起发挥作用,然后尝试将 NHibernate 重新添加到组合中。
标签: oracle nhibernate ado.net parameterized-query