具有ODBC的NHibernate-GenericADOException:无法插入
我编写了一个小程序,将一些记录插入oracle数据库。如果我直接连接到oracle,程序运行正常。但是,如果我尝试通过ODBC进行连接,该程序将无法工作。它可以执行具有ODBC的NHibernate-GenericADOException:无法插入,nhibernate,odbc,Nhibernate,Odbc,我编写了一个小程序,将一些记录插入oracle数据库。如果我直接连接到oracle,程序运行正常。但是,如果我尝试通过ODBC进行连接,该程序将无法工作。它可以执行SELECT语句,但不能执行INSERT语句 在开发程序时,我在NHibernate配置中使用了以下设置: <property name="connection.provider"> NHibernate.Connection.DriverConnectionProvider </property> &
SELECT
语句,但不能执行INSERT
语句
在开发程序时,我在NHibernate配置中使用了以下设置:
<property name="connection.provider">
NHibernate.Connection.DriverConnectionProvider
</property>
<property name="dialect">NHibernate.Dialect.Oracle10gDialect</property>
<property name="connection.connection_string">
Data Source=192.168.1.43:1521/xxxx;User ID=xxxx;Password=xxxx
</property>
<property name="connection.driver_class">
NHibernate.Driver.OracleClientDriver
</property>
<property name="hbm2ddl.keywords">auto-quote</property>
内部异常没有附加任何消息
我已经看过了NHibernate生成的SQL。使用开发设置,SQL
为输入生成的结果如下所示:
NHibernate: select STRUCTURE_SEQ.nextval from dual
NHibernate: INSERT INTO STRUCTURE_ASSIGN
(CLIENT_ID, STRUCTURE, NAME_CODE, START_DATE, STAT_SEQ)
VALUES (:p0, :p1, :p2, :p3, :p4);
:p0 = 'MAST17' [Type: String (6)],
:p1 = 'BENEFICIARY' [Type: String (11)],
:p2 = 27845 [Type: Int64 (0)],
:p3 = 28/10/2008 00:00:00 [Type: DateTime (0)],
:p4 = 42830 [Type: Int32 (0)]
NHibernate: select STRUCTURE_SEQ.nextval from dual
NHibernate: INSERT INTO STRUCTURE_ASSIGN
(CLIENT_ID, STRUCTURE, NAME_CODE, START_DATE, STAT_SEQ)
VALUES (?, ?, ?, ?, ?);
p0 = 'SCAR03' [Type: String (6)],
p1 = 'BENEFICIARY' [Type: String (11)],
p2 = 21525 [Type: Int64 (0)],
p3 = 07/11/1977 00:00:00[Type: DateTime (0)],
p4 = 35159 [Type: Int32 (0)]
com.Parameters.AddWithValue("?", (long)1234);
但是,使用生产设置时,生成的SQL如下所示:
NHibernate: select STRUCTURE_SEQ.nextval from dual
NHibernate: INSERT INTO STRUCTURE_ASSIGN
(CLIENT_ID, STRUCTURE, NAME_CODE, START_DATE, STAT_SEQ)
VALUES (:p0, :p1, :p2, :p3, :p4);
:p0 = 'MAST17' [Type: String (6)],
:p1 = 'BENEFICIARY' [Type: String (11)],
:p2 = 27845 [Type: Int64 (0)],
:p3 = 28/10/2008 00:00:00 [Type: DateTime (0)],
:p4 = 42830 [Type: Int32 (0)]
NHibernate: select STRUCTURE_SEQ.nextval from dual
NHibernate: INSERT INTO STRUCTURE_ASSIGN
(CLIENT_ID, STRUCTURE, NAME_CODE, START_DATE, STAT_SEQ)
VALUES (?, ?, ?, ?, ?);
p0 = 'SCAR03' [Type: String (6)],
p1 = 'BENEFICIARY' [Type: String (11)],
p2 = 21525 [Type: Int64 (0)],
p3 = 07/11/1977 00:00:00[Type: DateTime (0)],
p4 = 35159 [Type: Int32 (0)]
com.Parameters.AddWithValue("?", (long)1234);
代码中的其他内容没有改变-只有配置文件
有人知道这里出了什么问题吗?我怀疑是使用序列来生成表的ID(STAT_SEQ列),或者是导致第二组SQL中的参数是?
,而不是p0
,p1
等。NHibernate使用位置参数。通过查看DriverBase
可以看出,即使它在SQL语句中使用了“?”,NHibernate也会命名参数p0、p1、p2等。。。不幸的是,Oracle ODBC驱动程序不喜欢这样,这可以从对的响应中看出
解决您的问题的最简单的方法是创建一个自定义方言,该方言基于但带有我在下面包含的更改。此方言将生成名称为空字符串的参数,这是Oracle ODBC驱动程序所需的格式
请注意,我不是100%确定这是正确的格式,我已经看到一些示例,其中参数名称的格式为0、?1、?2等。。。但如果是这种情况,您可以修改ToParameterName
以返回StringHelper.SqlParameter+index
另外请注意,您不能仅从DriverBase
继承并重写必要的属性,因为所需的更改之一是静态属性
我还建议在上创建一个记录单,因为这种行为肯定是一个bug
public class OracleOdbcDriver : IDriver, ISqlParameterFormatter
{
....
public bool UseNamedPrefixInSql
{
get { return false; }
}
public bool UseNamedPrefixInParameter
{
get { return false; }
}
public string NamedPrefix
{
get { return string.Empty; }
}
....
private static string ToParameterName(int index)
{
return String.Empty;
}
....
}
哇,这确实是一个很难确定的问题 据我所知,错误在这一行:
p2 = 21525 [Type: Int64 (0)],
特别是,如果我将NameCode
的类型更改为int
而不是long
,则插入成功。不知何故,ODBC在64位整数上遇到了障碍。它中断时也没有任何类型的描述性错误消息,这非常令人沮丧。由于此问题仅在使用ODBC时出现,而不是在运行正常的OracleClientDriver
时出现,因此它一定是ODBC中的错误,而不是我的数据库配置问题
我还尝试直接使用ODBC:
var queryString = "insert into STRUCTURE_ASSIGN (CLIENT_ID, \"STRUCTURE\", NAME_CODE, STAT_SEQ, "
+ "START_DATE, FINISH_DATE, MEMO_NUMBER, ALTERNATE, ALTERNATE_NAME_CODE, ADMIN_NAME, "
+ "AUDIT_NAME, VALID_DATE, AUDIT_ACTION, DIRECTOR_CLASS) "
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?);";
using (var odbcConnection = new OdbcConnection(connectionString))
{
OdbcCommand com = new OdbcCommand(queryString, odbcConnection);
com.Parameters.AddWithValue("?", "aaa");
com.Parameters.AddWithValue("?", "aaa");
com.Parameters.AddWithValue("?", 1234);
com.Parameters.AddWithValue("?", 100000);
com.Parameters.AddWithValue("?", DateTime.Now);
com.Parameters.AddWithValue("?", DateTime.Now);
com.Parameters.AddWithValue("?", 1234);
com.Parameters.AddWithValue("?", 'N');
com.Parameters.AddWithValue("?", 1234);
com.Parameters.AddWithValue("?", "TRUST");
com.Parameters.AddWithValue("?", "TRUST");
com.Parameters.AddWithValue("?", DateTime.Now);
com.Parameters.AddWithValue("?", 'C');
com.Parameters.AddWithValue("?", 'A');
odbcConnection.Open();
var rd = com.ExecuteNonQuery();
odbcConnection.Close();
}
上述代码有效。但是,如果您像这样更改其中一行:
NHibernate: select STRUCTURE_SEQ.nextval from dual
NHibernate: INSERT INTO STRUCTURE_ASSIGN
(CLIENT_ID, STRUCTURE, NAME_CODE, START_DATE, STAT_SEQ)
VALUES (:p0, :p1, :p2, :p3, :p4);
:p0 = 'MAST17' [Type: String (6)],
:p1 = 'BENEFICIARY' [Type: String (11)],
:p2 = 27845 [Type: Int64 (0)],
:p3 = 28/10/2008 00:00:00 [Type: DateTime (0)],
:p4 = 42830 [Type: Int32 (0)]
NHibernate: select STRUCTURE_SEQ.nextval from dual
NHibernate: INSERT INTO STRUCTURE_ASSIGN
(CLIENT_ID, STRUCTURE, NAME_CODE, START_DATE, STAT_SEQ)
VALUES (?, ?, ?, ?, ?);
p0 = 'SCAR03' [Type: String (6)],
p1 = 'BENEFICIARY' [Type: String (11)],
p2 = 21525 [Type: Int64 (0)],
p3 = 07/11/1977 00:00:00[Type: DateTime (0)],
p4 = 35159 [Type: Int32 (0)]
com.Parameters.AddWithValue("?", (long)1234);
ODBC抛出与NHibernate包装相同的无用错误消息,因此这在NHibernate中不是错误
总结
如果遇到类似问题,请尝试将任何
long
变量更改为int
。您可能还想尝试切换其他字段的类型。您究竟为什么要将ODBC与具有受支持的本机驱动程序的数据库一起使用?@DiegoMijelshon他们都在客户端通过ODBC运行。我们尝试使用本机驱动程序,但无法在他们的站点上运行。我们不能在他们的系统上做太多的修改,所以我们可以更容易地让程序像他们现有的东西一样通过ODBC运行。非常感谢您的帮助。我没想到要换司机!我将研究并制定出使用的确切格式。我花了几个小时尝试使用各种不同的参数名称,但不幸的是,似乎没有一个有效。我可能不得不暂时搁置它,尝试另一种方法。