2

I tried to close a connection in the destructor of my class, to be sure that if I forget to close it - it close automatically, and it fires an exception.

I searched a little and I founded here that It can't be done.

Now I tried to close it twice - and it works!!!

But I'm wondering if it's a good solution. what do you think?

here is the code

public class MyCommand : IDisposable
{
    public readonly DbCommand command;
    public MyCommand(string ConnectionString, DbProviderFactory factory)
    {
        var tempConnexion = factory.CreateConnection();
        tempConnexion.ConnectionString = ConnectionString;
        tempConnexion.Open();
        var t = tempConnexion.BeginTransaction(IsolationLevel.ReadCommitted);
        command = tempConnexion.CreateCommand();
        command.Connection = tempConnexion;
        command.Transaction = t;
    }
    public MyCommand(string ConnectionString, DbProviderFactory factory, string requete)
        : this(ConnectionString, factory)
    {
        command.CommandText = requete;
    }
    public MyCommand(string ConnectionString, string provider)
        : this(ConnectionString, DbProviderFactories.GetFactory(provider)) { }
    public MyCommand(string ConnectionString, string provider, string requete)
        : this(ConnectionString, DbProviderFactories.GetFactory(provider), requete) { }

    public static implicit operator DbCommand(myCommand c)
    {
        return c.command;
    }
    public void Dispose()
    {
        try
        {
            var t = command.Transaction;
            if (t != null)
            {

                t.Commit();
                t.Dispose();
            }
        }
        catch { }
        try
        {
            if (command.Connection != null)
                command.Connection.Dispose();
            command.Dispose();
        }
        catch { }
    }
    ~MyCommand()
    {
        if (command != null && command.Connection != null && command.Connection.State == ConnectionState.Open)
            for (int i = 0; i < 2; i++)//twice to get the handle - it's working!
                Dispose();
    }
}
chmouel kalifa
  • 129
  • 2
  • 11

1 Answers1

5

The connection is closed by the Dispose method not by the Destructor.

Also see the MSDN caution

Caution

Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. In a finalizer, you should only release unmanaged resources that your class owns directly. If your class does not own any unmanaged resources, do not include a Finalize method in your class definition.

A much better and recommended way to deal with connection is to use USING statement which is equivalent to saying like

try
{
  // your code
}
finally
{
  myobject.Dispose();
}
Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331
  • yes. but if I forget to dispose - the destructor will dispose it. – chmouel kalifa Oct 07 '15 at 12:06
  • 2
    @chmouelkalifa Why do you forget to dispose in first place? Always use `using` statements. – Sriram Sakthivel Oct 07 '15 at 12:07
  • for the caution - I know, I refer to it. but it's working anyway.I just have to dispose it twice. Why not do it? – chmouel kalifa Oct 07 '15 at 12:09
  • @Sriram Sakthivel I agree, and I normally use the using statment, but I prefer to be sure (e.g. in one case I by mistake do that - `using(var c = new MyCommand(Sc,Sp).command)` and then the dispose go on the DBcomand and not to my class) – chmouel kalifa Oct 07 '15 at 12:12
  • @chmouelkalifa:- Its working since you are calling it twice which is not very good practice to follow. A better approach would be to use `using`. – Rahul Tripathi Oct 07 '15 at 12:13