为什么我的MysqlDataReader对象变为null?

时间:2012-01-31 08:43:19

标签: c# nullreferenceexception mysqldatareader

我有以下课程:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using MySql.Data.MySqlClient;

namespace DataBaseModule.General
{
    public class ManagedDataReader : IDisposable
    {

        private bool _disposed = false;
        private MySqlCommand _command;

        private MySqlDataReader _dataReader;
        // The class constructor.
        public ManagedDataReader(string StrSQL)
            : this(new MySqlCommand(StrSQL))
        {
        }

        public ManagedDataReader(MySqlCommand SQL_Cmd)
        {
            try
            {
                _command = SQL_Cmd;
                _command.Connection = new MySqlConnection(DbAccessProvider._connectionString);
                DbAccessProvider.SqlCommandsPerformed++;
                _command.Connection.Open();
                _dataReader = _command.ExecuteReader();
            }
            catch (Exception ex)
            {
                DataBaseModule.Log.CommonLogger.Log_Database_Error(new Exception("Sql command Was: " + _command.CommandText, ex));
                throw ex;
            }
        }

        public int VisibleFieldCount()
        {
            return _dataReader.VisibleFieldCount;
        }

        public bool Read()
        {
            return _dataReader.Read();
        }

        public object this[int i]
        {
            get
            {
                if (_dataReader[i].Equals(DBNull.Value))
                {
                    return null;
                }
                else
                {
                    return _dataReader[i];
                }
            }
        }

        public object this[string FieldName]
        {
            get
            {
                if (_dataReader[FieldName].Equals(DBNull.Value))
                {
                    return null;
                }
                else
                {
                    return _dataReader[FieldName];
                }
            }
        }

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue 
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the 
        // runtime from inside the finalizer and you should not reference 
        // other objects. Only unmanaged resources can be disposed.
        protected void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this._disposed)
            {
                // If disposing equals true, dispose all managed 
                // and unmanaged resources.
                if (disposing)
                {
                    if (_dataReader != null)
                    {
                        _dataReader.Close();
                    }
                    if (_command != null)
                    {
                        if (_command.Connection != null)
                        {
                            _command.Connection.Dispose();
                            _command.Connection = null;
                            //Free the reference.
                        }
                        _command.Dispose();
                    }
                }
                // Call the appropriate methods to clean up 
                // unmanaged resources here.
                // If disposing is false, 
                // only the following code is executed.
                // Note disposing has been done.
                _disposed = true;
            }
        }

        // This finalizer will run only if the Dispose method 
        // does not get called.
        // It gives your base class the opportunity to finalize.
        // Do not provide finalize methods in types derived from this class.
        ~ManagedDataReader()
        {
            // Do not re-create Dispose clean-up code here.
            // Calling Dispose(false) is optimal in terms of
            // readability and maintainability.
            Dispose(false);
        }
    }
}

我的问题是,由于某些原因,有时我在调用Read()时遇到异常: 例外是我的_dataReader成员为空。

这很奇怪,因为我在初始化时有try-catch块,没有捕获异常(我使用我的登录机制来检查)。

此行为很少见,但会出现aprox。每周一次(我每天运行数百万次查询)

非常感谢那些试图解决这个问题的人!

2 个答案:

答案 0 :(得分:2)

我想出了同样的问题。事实证明,在某些情况下,ExecuteReader()实际上可以返回null。

我查了连接器的代码,这就是我找到的:

catch (MySqlException ex)
{

...

// if we caught an exception because of a cancel, then just return null
if (ex.IsQueryAborted)
    return null;

当服务器返回 MySqlErrorCode.QueryInterrupted MySqlErrorCode.FileSortAborted 时,深入挖掘 IsQueryAborted 是正确的。到目前为止,事实证明这是一些服务器问题,至少在我的情况下,问题不一致,看起来像服务器代码中的多线程问题。

答案 1 :(得分:-1)

我查看了代码,我发现使用NULL读取器的唯一方法是在初始化代码中有一个例外。

由于SqlDataReader.ExecuteReader在所有情况下都返回一个对象,并且不能返回null。 Tatiana Racheva通过this answer中的反射SqlDataReader类确认了这一点。

拥有NULL读取器的第二种情况是,如果您在垃圾收集器处理ManagedDataReader对象后尝试使用读取器。