【问题标题】:"ORA-03115: unsupported network datatype or representation" when trying to to fill DataSet尝试填充 DataSet 时出现“ORA-03115:不支持的网络数据类型或表示”
【发布时间】:2019-08-19 15:51:43
【问题描述】:

我正在尝试用 OracleCommand 对象填充 DataSet 对象,我刚开始使用 Oracle,我一生都在使用 SQL Server。 在我的 NET 控制台项目中,我添加了 NuGet Oracle.ManagedDataAccess 包并将 Sql 对象更改为 Oracle。比如:SqlConnection 到 OracleConnection。 在 SQL Server 中它运行良好,但在 Oracle 中它给了我这个错误,我不太明白它的含义。

我将SqlConnection 更改为OracleConnectionSqlCommandOracleCommand

还有

command.Parameters.AddWithValue("@" + parameters[i], values[i] ?? DBNull.Value);

command.Parameters.Add(parameters[i], values[i] ?? DBNull.Value);
command.Parameters[i].Value = values[i];

因为AddWithValueOracleCommand 上不存在

这是从数据库中获取数据的方法。

        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 应该能够立即执行存储过程,但是您没有告诉它要执行哪个存储过程,或者我可能忽略了您的代码中的某些内容....

标签: c# oracle


【解决方案1】:

您需要为OUT 参数TestOut 添加OracleParameter,但您没有这样做。

在设置参数的其他行之后添加这些行:

    var outParam = new OracleParameter("TestOut", OracleDbType.RefCursor, ParameterDirection.Output);
    command.Parameters.Add(outParam);

然后您需要单独执行命令,而不是将命令传递给OracleDataAdapter。通过添加行来做到这一点

    command.ExecuteNonQuery();

紧跟在添加outParam的两个之后。

最后,通过替换行从OUT参数中的引用光标填充数据集

    new OracleDataAdapter(command).Fill(ds);

    new OracleDataAdapter().Fill(ds, (OracleRefCursor)outParam.Value);

顺便说一句,我在运行您的代码时遇到了另一个错误。我收到了错误PLS-00306: wrong number or types of arguments in call to 'GET_DATA'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-03
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    • 2019-06-07
    • 2015-02-17
    相关资源
    最近更新 更多