【发布时间】:2019-08-19 15:51:43
【问题描述】:
我正在尝试用 OracleCommand 对象填充 DataSet 对象,我刚开始使用 Oracle,我一生都在使用 SQL Server。 在我的 NET 控制台项目中,我添加了 NuGet Oracle.ManagedDataAccess 包并将 Sql 对象更改为 Oracle。比如:SqlConnection 到 OracleConnection。 在 SQL Server 中它运行良好,但在 Oracle 中它给了我这个错误,我不太明白它的含义。
我将SqlConnection 更改为OracleConnection
和SqlCommand 到OracleCommand
还有
command.Parameters.AddWithValue("@" + parameters[i], values[i] ?? DBNull.Value);
到
command.Parameters.Add(parameters[i], values[i] ?? DBNull.Value);
command.Parameters[i].Value = values[i];
因为AddWithValue 在OracleCommand 上不存在
这是从数据库中获取数据的方法。
private void GetData(string storedProcedure, IReadOnlyList<string> parameters, IReadOnlyList<object> values)
{
using (var connection = new OracleConnection(_connectionString))
{
using (
var command = new OracleCommand(storedProcedure, connection)
{
CommandType = CommandType.StoredProcedure
})
{
if (parameters != null)
for (var i = 0; i < parameters.Count; i++)
{
command.Parameters.Add(parameters[i], values[i] ?? DBNull.Value);
}
var ds = new DataSet();
connection.Open();
new OracleDataAdapter(command).Fill(ds);
_data = ds.Tables;
connection.Close();
}
}
}
这些是我使用的参数。
var db = new Connector.Provider("AIA.GET_DATA",
new[]{
"Test1",
"Test2",
"Test3",
"Test4"},
new object[]{
1,
2,
3,
null});
这就是存储过程。
PROCEDURE GET_DATA(
Test1 in NUMBER,
Test2 in NUMBER,
Test3 in NUMBER,
Test4 in NUMBER,
TestOut out SYS_REFCURSOR
);
在 Provider 的构造函数中,它获取连接字符串并使用 GetData 方法。
它失败了:
new OracleDataAdapter(command).Fill(ds);
Oracle.ManagedDataAccess.Client.OracleException: 'ORA-03115: 不支持的网络数据类型或表示'
同样,这在 SQL Server 上完美运行。
感谢任何帮助,至少,此错误消息是什么意思。
编辑:
谢谢卢克伍德沃德,这很有帮助。所以 OUT 参数有问题,而且我发送的参数类型也有问题。 这样就解决了问题。
无论如何,我最终采用了这种新方法。哪个工作正常,除了空值。
private void GetData(string storedProcedure, IReadOnlyList<string> parameters, IReadOnlyList<object> values, IReadOnlyList<string> cursors)
{
using (var connection = new OracleConnection(_connectionString))
{
using (
var command = new OracleCommand(storedProcedure, connection)
{
CommandType = CommandType.StoredProcedure
})
{
if (parameters != null)
for (var i = 0; i < parameters.Count; i++)
{
var parameter = new OracleParameter();
parameter.ParameterName = parameters[i];
if (values[i] is Enum)
parameter.Value = (int)values[i];
else
parameter.Value = values[i];
if (cursors != null && cursors.Contains(parameter.ParameterName))
{
parameter.Direction = ParameterDirection.Output;
parameter.OracleDbType = OracleDbType.RefCursor;
}
else
{
parameter.OracleDbType = GetOracleType(values[i]);
}
command.Parameters.Add(parameter);
}
var ds = new DataSet();
connection.Open();
new OracleDataAdapter(command).Fill(ds);
_data = ds.Tables;
connection.Close();
}
}
}
在Sql中我可以使用DBNull.Value,但是在Oracle中我需要定义OracleDbType,这很烦人,因为这个方法适用于任何对象,不关心类型,现在我仍然不知道如何修复它使其适用于 Oracle 中的任何对象。 但这可能被视为离题,此问题可以标记为已回答。
【问题讨论】:
-
Oracle 不是 SQL Server。 Oracle 中的处理方式与 SQL Server 中的不同。您不能简单地将 Sql 替换为 Oracle。你需要学习Oracle的做事方式。我建议投入一些时间和精力来探索如何以 Oracle 方式完成手头的任务。一个好的开始,至少对我来说,是相关的 Oracle 文档。
-
我不确定,但这似乎是整理数据的一些问题。我发现了几个可能的原因,从使用错误的 Oracle 客户端(32 位与 64 位)到 this question (java) 中提到的任何可能性。但除此之外,您的代码看起来很复杂。我认为 OracleCommand 应该能够立即执行存储过程,但是您没有告诉它要执行哪个存储过程,或者我可能忽略了您的代码中的某些内容....