具有命名参数问题的NHibernate CreateSQLQuery()

时间:2013-11-04 11:40:04

标签: oracle nhibernate ado.net parameterized-query

为什么命名或位置查询参数在我的情况下不适用于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:SET ROLE:p0 IDENTIFIED BY: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:SET ROLE:p0 IDENTIFIED BY: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:由MyPassword识别的SET ROLE MyRole] --->   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现在会在记录的异常中泄露密码。我不知道这里的问题是什么,这里没有干净的问题,因为我不知道该问什么,然后尖叫寻求帮助,希望有人可以对此有所了解。

在评论中进行了一些讨论后,我尝试了以下内容:

 ...
session.CreateSQLQuery(string.Format("SET ROLE {0} IDENTIFIED BY :rolePassword", 
                       roleName)) 
       .SetString("rolePassword", rolePassword)
       .ExecuteUpdate();
...

我试过两个:命名和? (位置)参数,单引号,双引号,似乎没有什么可行的。

此代码抛出了着名的ORA-00933: SQL command not properly ended错误

1 个答案:

答案 0 :(得分:2)

尝试使用.SetParameter()而不是SetString()。我目前正在使用类似的东西,它可以工作:

var cases = Session.CreateSQLQuery(sql)
            .SetParameter("someID",thisIsMyValue)
            .SetResultTransformer(NHibernate.Transform.Transformers.AliasToBean<SomeDTO>())
            .List<SomeDTO>();

SQL看起来像这样:

var sql = "SELECT fieldA, fieldB FROM myTable WHERE myTable.ID = :someID"