【问题标题】:How to call a Database Package Function in C#如何在 C# 中调用数据库包函数
【发布时间】:2013-08-16 19:15:54
【问题描述】:

我有这个代码;但是,当我尝试运行 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;
            }

【问题讨论】:

    标签: c# database plsql asmx remote-debugging


    【解决方案1】:

    这不起作用的原因是我错误地调用了该函数。 为了得到期望的结果,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;
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-17
      • 1970-01-01
      • 2015-03-15
      • 1970-01-01
      • 2021-09-02
      • 2016-12-17
      相关资源
      最近更新 更多