0

我有这个代码;但是,当我尝试运行 Invoke 时,第一个命令将起作用并返回正确的值,但 command2 在 C# 代码下方给出了一个错误。为什么 C# 看不到 EPA 包,我需要做些什么来修复它?

对此的任何帮助将不胜感激。

我试图在 PL/SQL 中调用的函数的签名是

FUNCTION NotificationGetNextID return integer;

其他潜在的重要信息:我正在使用此 DLL 访问数据库http://www.oracle.com/technetwork/database/windows/downloads/index-090165.html

//todo set all returns to void so that no one can see internal structure of db
internal static class Data
{
    private const String User = "xxx";
    private const String Pass = "xxx";
    private const String Source = "xxx";
    private const String DateFormat = "dd/MMM/yyyy";

    public static DatabasePackage DatabasePackageFactory(DatabasePackageType T)
    {
        switch (T)
        {
            case DatabasePackageType.EPA:
                return new EPA();
            default:
                return null;
        }

    }

    private class EPA : DatabasePackage
    {
        OracleConnection Conn;
        public EPA()
        {
            Conn = new OracleConnection();
            Conn.ConnectionString += "User Id=" + User + ";";
            Conn.ConnectionString += "Password=" + Pass + ";";
            Conn.ConnectionString += "Data Source=" + Source + ";";
            Conn.Open();
        }

        public object Invoke(String identifier, params String [] args)
        {
            //if you remove the commented out lines the code will not work, however now it works perfectly
            var Command = Conn.CreateCommand();
            //var Command2 = Conn.CreateCommand();

            //Command2.CommandType = CommandType.StoredProcedure;
            Command.CommandType = CommandType.Text;

            Command.CommandText = "select EPA.NotificationGetNextID from dual";// + identifier + parameters;
            //Command2.CommandText = "EPA.NotificationGetNextID";

            //var reader2 = ((Command2.ExecuteNonQuery()));
            var reader = ((Command.ExecuteReader()));

            reader.Read();
            return reader[0];
        }

        public void Dispose()
        {
            Conn.Close();
        }
    }
}

internal interface DatabasePackage : IDisposable
{
    object Invoke(String identifier, params String[] args);
}

internal enum DatabasePackageType
{
    EPA
}

错误 :

Oracle.DataAccess.Client.OracleException: ORA-06550: line 1, column 7:
PLS-00221: 'NOTIFICATIONGETNEXTID' is not a procedure or is undefined
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored
   at Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, String procedure, Boolean bCheck, Int32 isRecoverable)
   at Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, String procedure, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, Boolean bCheck)
   at Oracle.DataAccess.Client.OracleCommand.ExecuteNonQuery()
   at EPA.Data.EPA.Invoke(String identifier, String[] args)
   at EPA.ElectronicPriceAgreement.CompanyCreate()

打算如何使用

  using (DatabasePackage dbp = Data.DatabasePackageFactory(DatabasePackageType.EPA))
            {
                return dbp.Invoke("NotificationGetNextId");
                //return dbp.Invoke("CompanyCreate","key","description","","","","");
                //return result;
            }
4

1 回答 1

0

这不起作用的原因是我错误地调用了该函数。为了得到期望的结果,Invoke 必须是这样的

 public object Invoke(String identifier, params object[] args)
        {
            using (var Conn = new OracleConnection(ConnectionString))
            {
                using (var Command = new OracleCommand())
                {
                    Command.Connection = Conn;
                    Command.CommandText = "EPA."+ identifier;
                    Command.CommandType = CommandType.StoredProcedure;

                    using (var param = new OracleParameter())
                    {
                        param.OracleDbType = OracleDbType.Int32;
                        param.Direction = ParameterDirection.ReturnValue;
                        param.ParameterName = "return";
                        Command.Parameters.Add(param);
                    }
                    int nCount = 0;
                    foreach(object o in args)
                    {
                        using (var param = new OracleParameter())
                        {
                            param.OracleDbType = GetOracleDbType(o);
                            param.Direction = ParameterDirection.Input;
                            param.ParameterName = "arg" + nCount++;
                            param.Value = o;

                            if(param.OracleDbType != OracleDbType.Date)
                                Command.Parameters.Add(param);
                            else{
                                DateTime dt = (DateTime)o;
                                Command.Parameters.Add(dt.ToString(DateFormat),OracleDbType.Date).Value = dt;
                            }
                        }
                    }

                    Conn.Open();
                    Command.ExecuteNonQuery();
                    return Int32.Parse((Command.Parameters["return"].Value).ToString());
                }
            }
        }

首先,我需要关闭所有实现 IDipsosable 的对象。我最初没有做的事情。

其次,我需要将命令类型更改为 StoredProcedure,并设置返回类型。Oracle 关心顺序,所以应该按照函数接收它们的顺序来设置。回报应该是第一位的。

用于确定数据类型的函数是我从某个地方复制的,虽然我不记得我是从哪里获取的,但对于没有给予最初的创建者适当的信任,我深表歉意。

private OracleDbType GetOracleDbType(object o) 
        {
            if (o is string) 
                return OracleDbType.Varchar2;
            if (o is DateTime) 
                return OracleDbType.Date;
            if (o is Int64) 
                return OracleDbType.Int64;
            if (o is Int32) 
                return OracleDbType.Int32;
            if (o is Int16) 
                return OracleDbType.Int16;
            if (o is byte) 
                return OracleDbType.Byte;
            if (o is decimal) 
                return OracleDbType.Decimal;
            if (o is float) 
                return OracleDbType.Single;
            if (o is double) 
                return OracleDbType.Double;
            if (o is byte[]) 
                return OracleDbType.Blob;
            return OracleDbType.Varchar2;
        }
于 2013-08-22T12:22:39.373 回答