cha*_*r m 5 .net c# oracle ado.net odp.net
我做以下事情:
protected int CreateComponent(DbConnection cnctn, string tableName)
{
int newId;
DbCommand selectCmd = _provFactory.CreateCommand();
selectCmd.Connection = cnctn;
selectCmd.CommandText = string.Format(
"SELECT * FROM {0} WHERE ID = (SELECT MAX(ID) FROM {0})", tableName);
DbDataAdapter dataAdapter = _provFactory.CreateDataAdapter();
dataAdapter.SelectCommand = selectCmd;
...
// create Insert/Update/Delete commands with a builder for the data adapter
...
dataAdapter.Fill(_dataSet, tableName);
newId = Convert.ToInt32(_dataSet.Tables[tableName].Rows[0]["id"]) + 1000000;
DataRow newRow = _dataSet.Tables[tableName].NewRow();
newRow.ItemArray = _dataSet.Tables[tableName].Rows[0].ItemArray;
newRow["ID"] = newId;
_dataSet.Tables[tableName].Rows.Add(newRow);
}
Run Code Online (Sandbox Code Playgroud)
这适用于OleDb和System.Data.OracleClient.但是,使用Oracle.DataAccess.Client的提供程序,我得到:
Oracle.DataAccess.Types.OracleTruncateException (16550)
Run Code Online (Sandbox Code Playgroud)
文本截断结果源于:
at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors
at System.Data.Common.DbDataAdapter.UpdatedRowStatus
at System.Data.Common.DbDataAdapter.Update
at Oracle.DataAccess.Client.OracleDataAdapter.Update
at System.Data.Common.DbDataAdapter.UpdateFromDataTable
at System.Data.Common.DbDataAdapter.Update
Run Code Online (Sandbox Code Playgroud)
我得到的表是大表,其他包含61个字段.所有字段的类型仅限于:
VARCHAR2(different lenghts)
VARCHAR2(different lenghts) NOT NULL
FLOAT(126) NOT NULL
NUMBER NOT NULL
DATE
Run Code Online (Sandbox Code Playgroud)
编辑以防止过多评论:
- 我无法更改数据库中的数据类型或任何内容.
-In DataRow这些FLOAT(126)列的数据类型为System.Decimal(就像使用其他提供者时一样)
- 不像我之前说过的那样:ID不是主键.这是唯一的索引.表没有主键(作为Oracle定义)我不得不承认我认为唯一索引是主键,这对于熟悉Oracle的人来说可能听起来很荒谬.无论如何,我只插入1行.我没有尝试手工构建插入命令,我会稍微做一些.命令构建器应该处理没有PK的表(http://msdn.microsoft.com/en-us/library/tf579hcz.aspx:"SelectCommand还必须返回至少一个主键或唯一列.")
- 这也适用于ODP.NET/Oracle.DataAccess.Client,如果:
要么
的app.config:
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
<system.data>
<DbProviderFactories>
<add name="Oracle Data Provider for .NET"
invariant="Oracle.DataAccess.Client"
description="Oracle Data Provider for .NET"
type="Oracle.DataAccess.Client.OracleClientFactory,
Oracle.DataAccess,
Version=2.112.1.0,
Culture=neutral,
PublicKeyToken=89b483f429c47342" />
</DbProviderFactories>
</system.data>
Run Code Online (Sandbox Code Playgroud)
任何想法是什么原因以及我将如何让它适用于所有3个提供商?
谢谢和最诚挚的问候 - 马蒂
首先,我认为您应该将此作为错误报告给 Oracle。即使表非常小,也会发生错误。它与索引或主键无关,即使表没有索引也会发生错误。如果将 ID 的值设置为 0,则插入将运行正常。
我设法创建了一种解决方法,尽管它不是一个好方法,但对于您的情况来说可能已经足够了。
解决方法是使用 ODP.Net 的本机 Oracle 客户端类,因此您必须检查您的应用程序是否配置为 ODP 或其他之一,并相应地选择您的代码。
函数的“仅限 ODP”版本可能如下所示:
protected void CreateComponentODPOnly(Oracle.DataAccess.Client.OracleConnection cntn, string tableName)
{
int newId;
System.Data.DataSet _dataSet = new DataSet();
Oracle.DataAccess.Client.OracleCommand selectCmd = new Oracle.DataAccess.Client.OracleCommand();
selectCmd.Connection = cntn;
selectCmd.CommandText = string.Format(
"SELECT * FROM {0} WHERE ID = (SELECT MAX(ID) FROM {0})", tableName);
Oracle.DataAccess.Client.OracleDataAdapter dataAdapter = new Oracle.DataAccess.Client.OracleDataAdapter();
Oracle.DataAccess.Client.OracleCommandBuilder cmdBuilder = new Oracle.DataAccess.Client.OracleCommandBuilder();
dataAdapter.SelectCommand = selectCmd;
cmdBuilder.DataAdapter = dataAdapter;
dataAdapter.Fill(_dataSet, tableName);
newId = Convert.ToInt32(_dataSet.Tables[tableName].Rows[0]["id"]) + 1000000;
DataRow newRow = _dataSet.Tables[tableName].NewRow();
newRow.ItemArray = _dataSet.Tables[tableName].Rows[0].ItemArray;
newRow["ID"] = (Decimal)newId;
_dataSet.Tables[tableName].Rows.Add(newRow);
dataAdapter.InsertCommand = cmdBuilder.GetInsertCommand();
dataAdapter.Update(_dataSet.Tables[tableName]);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2148 次 |
| 最近记录: |