I am new to C#, I am programming an app in c# that requires the connection of an sqlite database. I thought it would be easiest for me to create my own DBConnection
class, which I have given below. The main problem I am having at the moment is with the destructor. Sometimes when I instantiate this class and it goes out of scope, I get a
System.ObjectDisposedException; 'Cannot access a disposed object. Object name: 'SQLiteConnection'.'
Now I have searched for a definition of what this means, but I don't really understand.
The object is being instantiated as part of a wpf app window, and this exception is thrown once the window is x'd out, and after database operations are finished.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Data.SQLite;
using System.IO;
namespace PhotoSuppliesInc
{
//this class will be used for connecting to the database in the various forms
public class DBConnector
{
//----------------------------------PRIVATES------------------------------//
//this is the connection to the db
private SQLiteConnection dbConnection;
//-------------------CONSTRUCTOR(S) and DESCTRUCTOR----------------//
public DBConnector()
{
string connectionString = "Data Source=C:\\Users\\dmand\\source\\repos\\PhotoSuppliesInc\\PhotoSuppliesInc\\database\\riverfrontphoto.db;" +
"Version = 3; FailIfMissing=True; Foreign Keys=True;";
try
{
dbConnection = new SQLiteConnection(connectionString);
dbConnection.Open();
MessageBox.Show("Database connected successfully");
}//end try
catch (SQLiteException e) { MessageBox.Show("error opening database"); }
}//end constructor
//destructor removes connection to database
~DBConnector()
{
dbConnection.Close();
}
//--------------------------------------------------GETTER(S)------------------------//
//public string Get_Filepath() { return filepath; }
//--------------------------------------------------UTILITY FUNCTIONS----------------//
public List<string> Select_Query(string query_string, string columns)
{
//the names of the columns in the select statement
string[] selection_columns = columns.Split();
//each member of the array is the tuple, the data is separated by spaces
List<string> result = new List<string>();
//this string constructs the result line to be inserted into the result list
string tempstring;
SQLiteCommand command = new SQLiteCommand(query_string, dbConnection);
SQLiteDataReader reader = command.ExecuteReader();
while (reader.Read())
{
tempstring = "";//reset the temp string for each tuple
int i = 0;
foreach(string s in selection_columns)
{
tempstring += reader[s] + " ";
i++;
}
//I'm not sure why result.add must go here, but it does
result.Add(tempstring);
}
//the result is a list who's contents are strings that represent each tuple
return result;
}
}//end class
}//end namespace
///////in LoginWindow.xaml.cs////
This how I am using the class in the window code file. ...
public LoginWindow()
{
itializeComponent();
//testing the DBConnector class:
DBConnector riverfront = new DBConnector();
string output_string = "";
foreach (string s in riverfront.Select_Query(@"select distinct fname || ' ' || lname as 'Full_Name', country from employee, employee_account limit 5", "Full_Name country"))
output_string += s + "\n";
MessageBox.Show(output_string);
}
...
As I said I don't know what this error means, or if I am properly using the destructor in this language. It seems to me like there should be no problem here. Can somebody help me figure out what this error means in my class? Thank you all for your time.
You are not properly using "destructors" because C# does not have destructors, it has finalizers.
The proper way to do what you're trying to do is to implement the IDisposable
pattern and access instances of your class within using
blocks.
Finalizers (denoted by the ~ syntax) are non-deterministic -- you cannot control when the garbage collector runs the finalizer, or if it ever does. Implementing IDisposable
and accessing instances within a using block allows you to implement deterministic cleanup of resources.
This is why you're getting an ObjectDisposedException
: Your class's finalizer is running after your instance of SQLiteConnection
is disposed.