none
为什么OracleDataReader 不能转换成DbDataReader RRS feed

  • 问题

  • OracleDataReader 是DbDataReader的子类 可是为什么OracleDataReader 不能转换成DbDataReader。比喻

    public DbDataReader ExecutDataReader(){

    return (new OracleDataReader())
    }

     报错说不能进行转换

    但是

    public DbDataReader ExecutDataReader(){

    return (new SqlDataReader())
    }

    却可以

    哈哈  这么多人看了都默默无语

    足见我提的问题多么高深

     

     

    2010年8月14日 10:54

全部回复

  • 呵呵,父类可以强制转换为子类,子类一般不能。

    因为通常子类都有一些特性,如果没有实现重载的方法在转换的时候会丢失,默认不容许这么转。


    family as water
    2010年8月14日 14:29
  • 但是

    public DbDataReader ExecutDataReader(){

    return (new SqlDataReader())
    }

    却可以

     

    2010年8月15日 0:16
  • 当然可以。 SqlDataReader 和 OracleDataReader 都可以转为其父类 DbDataReader。 请提供详细的错误信息以供分析真正错误。

    另外,你上面的代码是有问题的,根本无法编译通过,因为 SqlDataReader 和 OracleDataReader 都没有公共的构造函数让你 new,按设计约定任何 xxxDataReader 都只能有 xxxCommand.ExecuteReader 方法创建实例。 请提供合适的实例代码,以免误解。

    此外,注意到 Stone 上面的表述是有误的,子类对象可以无条件向像父类转换,父类对象可以强制子类转换,对于后者,如果类型不兼容,运行时才会抛出异常。


    问题要简单,错误须详细@错误/异常/堆栈信息+操作系统+软件版本+all the context of the issue Hope Helpful | http://www.leoworks.net
    2010年8月15日 4:51
  • 如果想让客户端代码与数据库类型解耦,可以尝试转成System.Data.IDataReader。个人认为面向System.Data.IDb*接口编码比较好。
    2010年8月15日 7:09
  • 这是源码了  目的是为了实现与多个数据库交互

    public interface IDataBase
        {
            int ExecuteNonQuery(DbTransaction trans,  CommandType cmdType, string cmdText, params DbParameter[] param);

            object ExecuteScalar(DbTransaction trans,  CommandType cmdType, string cmdText, params DbParameter[] param);

            DbDataReader ExecuteReader(DbTransaction trans,  CommandType cmdType, string cmdText, params DbParameter[] param);


        }

    Oracle的会报错

    public class OracleHelper:IDataBase
        {

            //解决同时为parameter赋值的麻烦
            private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

            private static string connString=null;

            private OracleConnection conn = null;

            #region IDataBase 成员

            public int ExecuteNonQuery(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] param)
            {
                OracleCommand cmd = new OracleCommand();
                PrepareCommand(cmd, trans, cmdType, cmdText, param);
                int ending = cmd.ExecuteNonQuery();
                cmd.Parameters.Clear();
                return ending;
            }

            private void PrepareCommand(OracleCommand cmd, DbTransaction trans, CommandType cmdType, string cmdText, DbParameter[] param)
            {
                throw new NotImplementedException();
            }

            public object ExecuteScalar(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] param)
            {
                using (OracleCommand cmd = new OracleCommand())
                {
                    PrepareCommand(cmd, trans, cmdType, cmdText, param);
                    object result = cmd.ExecuteOracleScalar();
                    cmd.Parameters.Clear();
                    return result;
                }
            }

            public DbDataReader ExecuteReader(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] param)
            {
                OracleCommand cmd = new OracleCommand();
                    PrepareCommand(cmd, trans, cmdType, cmdText, param);
                    OracleDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                    cmd.Parameters.Clear();
                //(DbDataReader)reader
                    return (DbDataReader)reader;//此处报错
            }

            #endregion

            /// <summary>
            /// Add a set of parameters to the cached
            /// </summary>
            /// <param name="cacheKey">Key value to look up the parameters</param>
            /// <param name="commandParameters">Actual parameters to cached</param>
            public static void CacheParameters(string cacheKey, params OracleParameter[] commandParameters)
            {
                parmCache[cacheKey] = commandParameters;
            }

            /// <summary>
            /// Fetch parameters from the cache
            /// </summary>
            /// <param name="cacheKey">Key to look up the parameters</param>
            /// <returns></returns>
            public static OracleParameter[] GetCachedParameters(string cacheKey)
            {
                OracleParameter[] cachedParms = (OracleParameter[])parmCache[cacheKey];

                if (cachedParms == null)
                    return null;

                // If the parameters are in the cache
                OracleParameter[] clonedParms = new OracleParameter[cachedParms.Length];

                // return a copy of the parameters
                for (int i = 0, j = cachedParms.Length; i < j; i++)
                    clonedParms[i] = (OracleParameter)((ICloneable)cachedParms[i]).Clone();

                return clonedParms;
            }

            /// <summary>
            /// Internal function to prepare a command for execution by the database
            /// </summary>
            /// <param name="cmd">Existing command object</param>
            /// <param name="conn">Database connection object</param>
            /// <param name="trans">Optional transaction object</param>
            /// <param name="cmdType">Command type, e.g. stored procedure</param>
            /// <param name="cmdText">Command test</param>
            /// <param name="commandParameters">Parameters for the command</param>
            private  void PrepareCommand(OracleCommand cmd, OracleTransaction trans, CommandType cmdType, string cmdText, OracleParameter[] commandParameters)
            {

                //Open the connection if required
                if (conn == null)
                    conn = new OracleConnection(connString);
                if (conn.State != ConnectionState.Open)
                    conn.Open();

                //Set up the command
                cmd.Connection = conn;
                cmd.CommandText = cmdText;
                cmd.CommandType = cmdType;

                //Bind it to the transaction if it exists
                if (trans != null)
                    cmd.Transaction = trans;

                // Bind the parameters passed in
                if (commandParameters != null)
                {
                    foreach (OracleParameter parm in commandParameters)
                        cmd.Parameters.Add(parm);
                }
            }

        }

    错误信息:

    错误 2 无法将类型“System.Data.OracleClient.OracleDataReader”转换为“System.Data.Common.DbDataReader” E:\C#\工作空间\窗体应用程序\Pig\PigDAL\OracleHelper.cs 57 24 PigDAL

    SqlServer 的不会报错

    class SqlHelper:IDataBase
        {

            private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable());

            private static string connString;

            public  string getConnString()
            {
               /* XPathDocument xpdoc = new XPathDocument(@"XMLFi.xml");
                string xpath = "/data/datatype[@level='SqlServer']";
                XPathNavigator xpn = xpdoc.CreateNavigator();
                XPathNodeIterator xpni = xpn.Select(xpath);
                foreach (object obj in xpni)
                {
                    connString = connString + obj.ToString();
                }
                return connString;
                */
                connString = "Data Source=.;Initial Catalog=books;Integrated Security=True";
                return connString;
            }

     

            private SqlConnection conn = null;

            #region IDataBase 成员

            public int ExecuteNonQuery(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] param)
            {
                SqlCommand cmd = new SqlCommand();
                PrepareCommand(cmd, trans, cmdType, cmdText, param);
                int ending = cmd.ExecuteNonQuery();
                cmd.Parameters.Clear();
                return ending;
            }

         

            public object ExecuteScalar(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] param)
            {
                using (SqlCommand cmd = new SqlCommand())
                {
                    this.PrepareCommand(cmd, trans, cmdType, cmdText, param);
                    object result = cmd.ExecuteScalar();
                    cmd.Parameters.Clear();
                    return result;
                }
            }

            public DbDataReader ExecuteReader(DbTransaction trans, CommandType cmdType, string cmdText, params DbParameter[] param)
            {
                SqlCommand cmd = new SqlCommand();
               
                PrepareCommand(cmd, trans, cmdType, cmdText, param);
                SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
                cmd.Parameters.Clear();
                return reader;
            }

            #endregion

            /// <summary>
            /// Add a set of parameters to the cached
            /// </summary>
            /// <param name="cacheKey">Key value to look up the parameters</param>
            /// <param name="commandParameters">Actual parameters to cached</param>
            public static void CacheParameters(string cacheKey, params SqlParameter[] commandParameters)
            {
                parmCache[cacheKey] = commandParameters;
            }

            /// <summary>
            /// Fetch parameters from the cache
            /// </summary>
            /// <param name="cacheKey">Key to look up the parameters</param>
            /// <returns></returns>
            public static SqlParameter[] GetCachedParameters(string cacheKey)
            {
                SqlParameter[] cachedParms = (SqlParameter[])parmCache[cacheKey];

                if (cachedParms == null)
                    return null;

                // If the parameters are in the cache
                SqlParameter[] clonedParms = new SqlParameter[cachedParms.Length];

                // return a copy of the parameters
                for (int i = 0, j = cachedParms.Length; i < j; i++)
                    clonedParms[i] = (SqlParameter)((ICloneable)cachedParms[i]).Clone();

                return clonedParms;
            }

            /// <summary>
            /// Internal function to prepare a command for execution by the database
            /// </summary>
            /// <param name="cmd">Existing command object</param>
            /// <param name="conn">Database connection object</param>
            /// <param name="trans">Optional transaction object</param>
            /// <param name="cmdType">Command type, e.g. stored procedure</param>
            /// <param name="cmdText">Command test</param>
            /// <param name="commandParameters">Parameters for the command</param>
            private  void PrepareCommand(DbCommand cmd, DbTransaction trans, CommandType cmdType, string cmdText, DbParameter[] commandParameters)
            {

                //Open the connection if required
                if (conn == null)
                    conn = new SqlConnection(this.getConnString());
                if (conn.State != ConnectionState.Open)
                    conn.Open();

                //Set up the command
                cmd.Connection = conn;
                if(cmdText!=null)
                cmd.CommandText = cmdText;
                if(cmdType!=null)
                cmd.CommandType = cmdType;

                //Bind it to the transaction if it exists
                if (trans != null)
                    cmd.Transaction = trans;

                // Bind the parameters passed in
                if (commandParameters != null)
                {
                    foreach (SqlParameter parm in commandParameters)
                        cmd.Parameters.Add(parm);
                }
            }
        }

     

     


    原谅我这一生不羁放纵爱自由
    2010年8月15日 9:31
  • 可不可讲详细点 关于IDB
    原谅我这一生不羁放纵爱自由
    2010年8月15日 9:36