本帖最后由 caozhy 于 2013-08-14 21:37:50 编辑

解决方案 »

  1.   

    如果你用Oracle.DataAccess.dll,就必须设置 cmd.BindByName = true; 我没看到有设置这句的地方,错误提示就是你的参数是安装顺序而不是名称进行绑定的。
    另外没必要使用反射,而且反射也会导致部分功能无法使用,例如这个BindByName在DbCommand里面是不存在的。
    如果要解决Oracle 版本号不一致的问题,很容易,修改配置文件的运行时版本号兼容即可。
      

  2.   

    配置文件举例如下:
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Oracle.DataAccess"
            publicKeyToken="89B483F429C47342"
            culture="neutral" />
            <bindingRedirect
              oldVersion="2.112.2.0"
              newVersion="2.112.1.0"/>
          </dependentAssembly>
        </assemblyBinding>
        <Thread_UseAllCpuGroups enabled="true"/>
        <GCCpuGroup enabled="true"/>
        <gcServer enabled="true"/>
      </runtime>
    这是用的11G的客户端,由于10G客户端很多问题,因此不建议使用,而且高版本客户端兼容低版本服务端。
    newVersion="2.112.1.0"是11g的64位版本号,而oldVersion="2.112.2.0"是11g的32位版本号,这里oldVersion就用开发用的版本号,而newVersion则使用客户安装的版本号,如果不清楚版本号,可以在注册表里查看,例如使用安装程序在安装时,检测注册表HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ODP.NET\2.112.2.0分支,最后那个就是版本号,动态产生程序配置文件。
      

  3.   

    DbCommand里 没有 BindByName 但是我可以用反射做到的,明天我给你贴代码。你就知道了。我自己写了一个数据库的访问器 公司在用,最初的时候一直用 System.Data.OracleClient 因为参数问题,就换成 Oracle.DataAccess.dll了。因为我的目的是 不需要别人去因为我的 Accessor 所以就用反射了。
    因为 oracle x64 和 x86 客户的服务器配置不一定还。就用反射了。
      

  4.   

    不过你那种 方法也可以,但是有问题存在, 如果你引用了 那个Oracle.DataAcess.dll 每次都要编译下,反射动态加载了 ,因为我不想总编译。我写了一个工厂类,完全可以 处理掉了。只是在 调用分页存储过程的时候输出参数是游标,一直抱参数问题。其他人说,out参数也要赋值才可以,不知道是不是这个问题引起的。
      

  5.   

    DbCommand里 没有 BindByName 但是我可以用反射做到的,我初始化的是 OracleCommand 对象,BindBodyName = true;
    然后我吧 OracleComand 给 DbComand了,因为我那个数据库访问器 是多数据库兼容的,所以就有 基础Command类了,明天试试你那个 runtime config 如果可以,那就不用反射了。省点事还。
    我当初用 config 来着,因为不起作用,我就用反射了。 
    就 refcursor 在用 datareader读的时候有问题。
    其他反射都做了。
      

  6.   

    在exe.config里面配置了runtime节点后,就不需要每次都编译了,一次编译后,dll版本更换只要修改配置文件即可。而out参数是不需要赋值的,反射设置值的时候可以这样
    parameters[0].GetType().GetProperty("OracleDbType").SetValue(parameters[0], Enum.Parse(oracleDbType,"RefCursor"), null);
      

  7.   

    昨天说的你没有看到  BindBodyName 这个代码如下。      /// <summary>
            /// 方法描述:重写父类创建Command对象的方法
            /// 异常:ArchStar.Framework.Exceptions.DbHelperException
            /// </summary>
            /// <param name="dbConnection">数据库连接对象</param>
            /// <param name="commandType">命令类型 默认:存储过程</param>
            /// <param name="commandText">命令文本</param>
            /// <param name="parameters">命令参数</param>
            /// <returns>数据库命令对象</returns>
            protected override DbCommand CreateDbCommand(DbConnection dbConnection, System.Data.CommandType commandType, StringBuilder commandText, params DbParameter[] parameters)
            {
                DbCommand cmd = null;
                try
                {
                    try
                    {
                        if (dbConnection.State != ConnectionState.Open)
                            dbConnection.Open();
                    }
                    catch (InvalidOperationException ex)
                    {
                        throw new DbHelperException(ex.Message, ex);
                    }
                    cmd = factory.CreateInstance<DbCommand>(ManifestConst.ORACLE_DATAACCESS_CLIENT_ORACLECOMMAND);
                    cmd.GetType().GetProperty("BindByName").SetValue(cmd, true, null);
                    using (cmd)
                    {
                        cmd.Connection = dbConnection;
                        cmd.CommandType = commandType;
                        cmd.CommandText = commandText.ToString();
                        cmd.CommandTimeout = this.CommandTimeout;
                        SetDbCommandParameters(cmd, parameters);
                    }
                }
                catch (DbException ex)
                {
                    throw new DbHelperException(ex.Message, ex);
                }
                return cmd;
            }
      

  8.   

     /// <summary>
            /// 方法描述:重写父类创建Command对象的方法
            /// 异常:ArchStar.Framework.Exceptions.DbHelperException
            /// </summary>
            /// <param name="dbConnection">数据库连接对象</param>
            /// <param name="commandType">命令类型 默认:存储过程</param>
            /// <param name="commandText">命令文本</param>
            /// <param name="parameters">命令参数</param>
            /// <returns>数据库命令对象</returns>
            protected override DbCommand CreateDbCommand(DbConnection dbConnection, System.Data.CommandType commandType, StringBuilder commandText, params DbParameter[] parameters)
            {
                DbCommand cmd = null;
                try
                {
                    try
                    {
                        if (dbConnection.State != ConnectionState.Open)
                            dbConnection.Open();
                    }
                    catch (InvalidOperationException ex)
                    {
                        throw new DbHelperException(ex.Message, ex);
                    }
                    cmd = factory.CreateInstance<DbCommand>(ManifestConst.ORACLE_DATAACCESS_CLIENT_ORACLECOMMAND);
                    using (cmd)
                    {
                        cmd.Connection = dbConnection;
                        cmd.CommandType = commandType;
                        cmd.CommandText = commandText.ToString();
                        cmd.CommandTimeout = this.CommandTimeout;
                        SetDbCommandParameters(cmd, parameters);
                        cmd.GetType().GetProperty("BindByName").SetValue(cmd, true, null);
                    }
                }
                catch (DbException ex)
                {
                    throw new DbHelperException(ex.Message, ex);
                }
                return cmd;
            }红色就是绑定的,先加参数已经加进去了。BindBodyName 也设置成 true了。
    就是DataReader 还是那个问题。
      

  9.   

    Connection和Command 都可以了。BindBodyName = true也。
    就是DataReader时候出问题。
    我用的 DataReader 也是基础的。
      

  10.   

    /*
      功能描述:公共分页存储过程
      编写人:Joe
      编写日期:2013年06月27日
      版权:Copyright © Archstarcn
    */
    CREATE OR REPLACE PACKAGE PACKAGE_COMMONPAGING IS
    TYPE DATASET IS REF CURSOR;
    PROCEDURE PROCEDURE_COMMONPAGING
    (
    RESULTS OUT DATASET,--返回的结果集合
    TOTALRECORDCOUNT OUT INT,--总记录数
    TOTALPAGECOUNT OUT INT, --总页数 
    PAGEINDEX IN INT,--页索引
    PAGESIZE IN INT,--每页的数量
    INPUTSQLSTRING IN VARCHAR2,--输入的SQL语句字符串
    ORDERBY IN VARCHAR2--要排序的字段名。格式:{Field1 [SortMode(DESC | ASC)]......,n [SortMode(DESC | ASC)]}
    );
    END PACKAGE_COMMONPAGING;
    /
    这是包头的类型,
      

  11.   

    参数顺序正确的话,检查下每个输入型参数的值,对于输入参数,为空的话要用DbNull.Value传递进去,而不能传递null,传递null会自动把该参数给忽略,导致缺少了参数。
      

  12.   

    你用反射的目的应该是为了通用化,但是你却针对具体SQL的参数进行反射处理,失去了通用化,适得其反,
    建议你参考下Dapper的处理方式。
    提示:IDbCommand的CreateParameter方法可以直接创建参数,这部分完全可以不使用反射。
      

  13.   

    用不用 这个 :IDbCommand的CreateParameter 不是重点。 关键是 不管用什么方式都是那一个错误。
      

  14.   

    而且你用 IDbCommand的CreateParameter 你不用反射你就还得用 引用的方式来 进行单个参数的赋值。反射这面没有问题。值早就都可以了。只是不管用什么方式, 他都提示。上面的错误。
    我换其他的方法调用测试的时候 他提示 所有参数未绑定。BindByName = true了
    变量没有空也。
      

  15.   

      /// <summary>
            /// 数据库命令参数装载
            /// </summary>
            /// <param name="dbCommand">数据库命令对象</param>
            /// <param name="parameters">数据库命令参数</param>
            protected virtual void SetDbCommandParameters(IDbCommand dbCommand, params IDbDataParameter[] parameters)
            {
                if (dbCommand == null)
                    return;
                if (parameters == null || parameters.Length == 0)
                    return;
                foreach (var param in parameters)
                    dbCommand.Parameters.Add(param);
            }参数在这里加的。
      

  16.   

    那你写个测试用的存储过程,输出参数只有游标,不带任何其它参数,看看是否正常。
    如果正常-->那就是返回类型不是int的,事实上你也无法指定精度,Oracle里面的number类型是非常大的数字,对应的数据类型用Int64都不为过,而且似乎默认是Decimal类型的。
    注意:输出参数的数据类型和精度都很重要,对于String类型,必须设置其字符数,默认字符数为1.
      

  17.   

    我的反射已经可以了,不过参数还是无法对应绑定上
    就3个参数的一个删除语句还是无法对应。用如下代码  
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Oracle.DataAccess" publicKeyToken="89B483F429C47342"/>
            <bindingRedirect oldVersion="4.112.0.0-4.112.3.0" newVersion="2.112.1.0"/>
          </dependentAssembly>
        </assemblyBinding>根本就不起作用。
      

  18.   

    oldVersion错了啊,版本号只能是一个,你怎么填写了一个范围?
    oldVersion是你Visual Studio里面添加的那个dll的版本号,编译后,exe程序肯定只认那个版本号,为了兼容其它版本号,才需要转换为newVersion,一般情况下,一个项目里面只可能用到一个版本号,除非你引用的其它dll也用到了但是版本号不同的Oracle.DataAccess.dll,完整的写法如下,你可以尝试<bindingRedirect节点多写一次,反正我没试过。
    <configuration>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Oracle.DataAccess"
            publicKeyToken="89B483F429C47342"
            culture="neutral" />
            <bindingRedirect
              oldVersion="2.112.2.0"
              newVersion="2.112.1.0"/>
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>