views:

98

answers:

3

I'm writing some console applications to move some data between SQLite databases. The classes for the connection and various prepared statements implenent IDisposable, so I'm instantiating these objects using using blocks, like this:

using (SQLiteConnection sqlite_conn = new SQLiteConnection(connectionString))
{
    sqlite_conn.Open();
    using (SQLiteCommand sqlite_cmd = new SQLiteCommand())
    {
        sqlite_cmd.Connection = sqlite_conn;
        sqlite_cmd.CommandText = "INSERT INTO SOMETHING SOMETHING;";
        sqlite_cmd.ExecuteNonQuery();
    }
    sqlite_conn.Close();
}

But, I need to be able to create these connections in one method, and then call them in other methods. What is the cleanest and least confusing way for me to store these connections as instance variables? I want to make sure their .Dispose() methods are called in an intelligent way, but can't see a good way to make sure all of the action occurs within the context of a single using block.

I realize this is a C# newb question so please tailor your answers as such. If you have a suggested solution, I'd love it if you included a code sample to illustrate.

EDIT: My use case is a console app. Someone passes in the source and destination connection strings, and the console app performs an operation. Would I actually make my console class Program itself implement IDisposable like this?:

class Program : IDisposable
{
    private SQLiteConnection sourceConnection;
    private SQLiteConnection destinationConnection;

    public void Dispose()
    {
        sourceConnection.Dispose();
        destinationConnection.Dispose();
    }  
}
+2  A: 

I need to be able to create these connections in one method, and then call them in other methods. What is the cleanest and least confusing way for me to store these connections as instance variables?

In this case, the class where you keep these instance variables should itself implement IDisposable, and on disposal should make sure the connections are also disposed.

Also, when you have multiple IDisposables at once you can re-write it this way, to group them and reduce the nesting in the code:

using (SQLiteConnection sqlite_conn = new SQLiteConnection(connectionString))
using (SQLiteCommand sqlite_cmd = new SQLiteCommand())
{
    sqlite_conn.Open();

    sqlite_cmd.Connection = sqlite_conn;
    sqlite_cmd.CommandText = "INSERT INTO SOMETHING SOMETHING;";
    sqlite_cmd.ExecuteNonQuery();
} // no need to call .Close(): IDisposable normally handles it for you
Joel Coehoorn
Totally useful and valuable information to me. However, it doesn't show a good sample of the kind of class design I would need. In a console app, would I implement IDisposable for the Program class itself? I'll add details to my original question.
danieltalsky
Okay, Edit added with a sample of how I interpret this.
danieltalsky
No, the program class should not implement IDisposable. You should NOT normally keep a connection to a database active for the life of your program, unless you expect your program to be very short lived (which admittedly is possible for a console app; you might mean it to run in a quick batch script with no user interaction after it starts).Instead, just recreate the connection in each little method as often as you need to. The db provider implementations in .Net normally pool them to keep this efficient.
Joel Coehoorn
Interesting! I did not realize this, and assumed that creating a new connection for each transaction would be extremely wasteful. It certainly is more verbose! The reason I actually moved away from this strategy in the first place was because I saw my application writes slowing down CONSIDERABLY over the life of the application. Is this perhaps a weakness in the library I'm using? A LOT of data is being inserted over the life of the program.
danieltalsky
Maybe share exactly what you're trying to do, and we can help you put it together in an efficient way.
Joel Coehoorn
+1  A: 

You can make your class implement IDisposable and ensure you clean up the connection etc within your Dispose method. Then the method calling your class can do using(MyClass c ...).

Steven
+1  A: 

One way is to have your class implement IDisposable. In your class's Dispose method, call the Dispose methods of the connection and the command etc. Then you can use an instance of your class in a using block.

Logan Capaldo