Search code examples
c#garbage-collectiondisposeidisposable

Types that own disposable fields should be disposable. how to solve this warning?


I tried using Run Code Analysis option in VisualStudio 2012, as a result of it I got a warning as

CA1001  Types that own disposable fields should be disposable
Implement IDisposable on 'DBConnectivity' 
because it creates members of the following IDisposable types: 'SqlConnection', 'SqlCommand'.

I referred some question in SO, but I couldn't catch the point regarding IDisposable and following is the class, responsible for this warning.

class DBConnectivity
    {
        public SqlConnection connection = null;
        public SqlCommand command = null;
        public SqlDataReader dataReader = null;
        public string connectionString = null;
        public List<MasterTableAttributes> masterTableList;
        public DBConnectivity()
        {
            connectionString = ConfigurationManager.ConnectionStrings["Master"].ConnectionString;
            connection = new SqlConnection(connectionString.ToString());

            //-----Master table results 
            connection.Open();
            string masterSelectQuery = "SELECT * FROM MASTER_TABLE";
            command = new SqlCommand(masterSelectQuery, connection);
            dataReader = command.ExecuteReader();
            masterTableList = new List<MasterTableAttributes>();

            while (dataReader.Read())
            {
                MasterTableAttributes masterTableAttribute = new MasterTableAttributes()
                {
                    fileId = Convert.ToInt32(dataReader["Id"]),
                    fileName = Convert.ToString(dataReader["FileName"]),
                    frequency = Convert.ToString(dataReader["Frequency"]),
                    scheduledTime = Convert.ToString(dataReader["Scheduled_Time"])
                };
                masterTableList.Add(masterTableAttribute);
            }
            dataReader.Close();
            connection.Close();
        }
    }

I am really confused in implementing the IDisposable. Any help appreciated?


Solution

  • I fully agree with the compiler - you need to dispose your fields here, or (as already noted) - not make them fields in the first place:

    class DBConnectivity : IDisposable // caveat! read below first
    {
        public void Dispose() {
            if(connection != null) { connection.Dispose(); connection = null; }
            if(command != null) { command.Dispose(); command = null; }
            if(dataReader != null) { dataReader.Dispose(); dataReader = null; }
        }
    

    Note that you would then use this type via using(...)


    However! It looks like a static method would be more appropriate:

    static class DBConnectivity
    {
        public static List<MasterTableAttributes> GetMasterTableList()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["Master"].ConnectionString;
            using(var connection = new SqlConnection(connectionString))
            {
                connection.Open();
                const string masterSelectQuery = "SELECT * FROM MASTER_TABLE";
                using(var command = new SqlCommand(masterSelectQuery, connection))
                using(var dataReader = command.ExecuteReader())
                {
                    var masterTableList = new List<MasterTableAttributes>();
    
                    while (dataReader.Read())
                    {
                        MasterTableAttributes masterTableAttribute = new MasterTableAttributes()
                        {
                            fileId = Convert.ToInt32(dataReader["Id"]),
                            fileName = Convert.ToString(dataReader["FileName"]),
                            frequency = Convert.ToString(dataReader["Frequency"]),
                            scheduledTime = Convert.ToString(dataReader["Scheduled_Time"])
                        };
                        masterTableList.Add(masterTableAttribute);
                    }
                    return masterTableList;
                }
            }
        }
    }
    

    or perhaps simpler with a tool like "dapper":

    static class DBConnectivity
    {
        public static List<MasterTableAttributes> GetMasterTableList()
        {
            var connectionString = ConfigurationManager.ConnectionStrings["Master"].ConnectionString;
            using(var connection = new SqlConnection(connectionString))
            {
                connection.Open();
                const string sql = "SELECT Id as [FileId], FileName, Frequency, Scheduled_Time as [ScheduledTime] FROM MASTER_TABLE";
                return connection.Query<MasterTableAttributes>(sql).ToList();
            }
        }
    }