gpt4 book ai didi

c# - 为什么我在调用 DbDataAdapter.Update 时使用 ODP.NET OracleDataAdapter 而不是使用 System.Data.OracleClient 的适配器获得 OracleTruncateException?

转载 作者:太空狗 更新时间:2023-10-29 23:47:45 24 4
gpt4 key购买 nike

我做了以下事情:

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);
}

这非常适用于 OleDb 和 System.Data.OracleClient。但是,对于 Oracle.DataAccess.Client 的提供者,我得到:

Oracle.DataAccess.Types.OracleTruncateException (16550) 

文本截断结果源自:

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

我得到的表是其他包含61个字段的大表。所有字段的类型仅限于:

VARCHAR2(different lenghts)
VARCHAR2(different lenghts) NOT NULL
FLOAT(126) NOT NULL
NUMBER NOT NULL
DATE

编辑以防止评论过多:

-我无法更改数据库中的数据类型或任何内容。

-在 DataRow 中,这些 FLOAT(126) 列的数据类型为 System.Decimal(就像使用其他提供程序时一样)

- 与我之前声明的不同:ID 不是主键。它是唯一索引。表没有主键(如 Oracle 定义) 我不得不承认,我认为唯一索引是主键,这对于熟悉 Oracle 的人来说可能听起来很荒谬。无论如何,我只插入 1 行。我还没有尝试手动构建 Insert-command,我稍后会做。命令构建器应该处理没有 PK 的表(http://msdn.microsoft.com/en-us/library/tf579hcz.aspx:“SelectCommand 还必须返回至少一个主键或唯一列。”)

-这也适用于 ODP.NET/Oracle.DataAccess.Client,如果:

  • 我在方法的最后一个之前给所有 FLOAT(126) 列值 0排。即使给任何值 1 或 2 也会引发相同的异常调用 DbDataAdapter.Update。

  • 我自己创建了 DbDataAdapter.Insertommand,只有在调用 DbDataAdapter.Update 时插入(如上面的代码)。当我自己构建 cmd 时,我为 FLOAT(126) 列提供 DbParameter.DbType = DbType.Double。如果我自己构建它,则接受所有正常的 double 值。

应用程序配置:

<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>

任何想法是什么原因以及我将如何使其适用于所有 3 个提供商?

谢谢和最好的问候 - Matti

最佳答案

首先,我认为您应该将此作为错误报告给 Oracle。即使表真的很小,也会发生错误。与索引和主键无关,即使表没有索引也会报错。如果将 ID 的值设置为 0,则插入将正常运行。

我设法创建了一个解决方法,虽然它不是一个好方法,但它可能足以满足您的情况。

解决方法是为 ODP.Net 使用 native 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]);
}

关于c# - 为什么我在调用 DbDataAdapter.Update 时使用 ODP.NET OracleDataAdapter 而不是使用 System.Data.OracleClient 的适配器获得 OracleTruncateException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8095082/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com