如何在C#中调用数据库包函数

时间:2013-08-14 17:32:54

标签: c# database plsql asmx remote-debugging

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

1 个答案:

答案 0 :(得分: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;
        }