I read I need to implement IDisposable
if my class has a member variable that is itself IDisposable. Well, I am implementing IDisposable
interface because my class contains a database object (db
class member below) which is IDisposable itself:
public class CommissionModel : IDisposable
{
protected PetaPoco.Database db;
public CommissionModel()
{
string connectionString = "Server=localhost;...";
// The line below may throw an exception (!!!)
db = new PetaPoco.Database(connectionString, "mysql");
}
// Automatically close database connection
public void Dispose()
{
if (db != null)
db.Dispose();
db = null;
}
public void InsertRecord(Record somerecord)
{
// ...
db.Insert(somerecord);
}
The problem is instantiation of db
member may fail under some circumstances.
What should I do when the exception is thrown in the constructor and the database object gets not created? Should I rethrow the exception or maybe check if db != null
in InsertRecord method?
If your class creates unmanaged resources, then you can implement IDisposable so that these resources will be cleaned up properly when the object is disposed of. You override Dispose and release them there.
If an object doesn't implement IDisposable , then you don't have to dispose of it. An object will only expose Dispose if it needs to be disposed of.
Typically, types that use unmanaged resources implement the IDisposable or IAsyncDisposable interface to allow the unmanaged resources to be reclaimed. When you finish using an object that implements IDisposable, you call the object's Dispose or DisposeAsync implementation to explicitly perform cleanup.
If a type implements the IDisposable interface, you should always call the Dispose method on an instance of the class when you are done using it. The presence of IDisposable indicates that the class has some resources that can be released prior to garbage collection.
If your constructor throws an exception, the consumer of your code will never receive a reference to an instance of your class. The partially initialized class memory will eventually be collected and Dispose will not be called.
I would generally recommend moving an operation that can fail due to outside circumstances (and not due to misusage, like an invalid parameter value) to a separate method, like "Connect".
Ideally you should not be doing any "work" in the constructor. Work in the constructor should really be linking up object references. This would allow you to unit test this class by hooking up mock classes instead.
Try this instead:
public CommissionModel(PetaPoco.Database db) {
this.db = db;
}
It looks like you don't have to do anything.
If your construction process is interrupted the resource is not created. In most usage scenarios (this lays outside your class), the Dispose() will never be called. But even when it is, your if (db != null)
code is enough of a guard.
A few minor points:
db = null;
inside Dispose() is pointless.InsertRecord()
should start by checking if (db != null)
You should only catch exceptions that you can handle. From the code, it appears that initializing the variable db may show that there is a problem communicating with your database server.
My suggestion is to leave your code as is and handle exceptions in a central location such as the Application_Error event in the Global.asax or the event that is initializing the CommissionModel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With