30

I've always used using with variable and assignment. Now i have like this a class DbProviderConnection:

public class DbProviderConnection : IDisposable
{
    public DbConnection Connection { get; set; }
    public DbTransaction Transaction { get; set; }

    public DbTransaction BeginTransaction()
    {
        Transaction = Connection.BeginTransaction();
        return Transaction;
    } 

    //... and so on
}

Now i was thinkin to use it like this:

using (DbProviderConnection cnctn = _planDb.CreateOpenConnection())
{
    using (cnctn.BeginTransaction())
    {
        //...
        cnctn.Transaction.Commit();
    }
}

My question is: Is the DbProviderConnection.Transaction.Dispose called?

anar khalilov
  • 16,993
  • 9
  • 47
  • 62
char m
  • 7,840
  • 14
  • 68
  • 117

4 Answers4

30

From C# Specification 8.13 using statement defined as

using-statement:
   using (resource-acquisition) embedded-statement

Where resource-acquisition is

resource-acquisition:
    local-variable-declaration
    expression

In first case you have using which acquires resource via local variable declaration. In second case resource is acquired via expression. So, in second case resouce will be result of cnctn.BeginTransaction() call, which is DbTransaction from your DbProviderConnection class. Using statement disposes its resource after usage. So, yes, DbProviderConnection.Transaction.Dispose() will be called.

UPDATE: According to same article, your second using block will be translated to

DbTransaction resource = cnctn.BeginTransaction();
try
{
    //...
    cnctn.Transaction.Commit();
}
finally 
{
   if (resource != null) 
      ((IDisposable)resource).Dispose();
}
Mariano Desanze
  • 7,847
  • 7
  • 46
  • 67
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • @matti welcome :) I also added link to specification which describes how `using` statement works – Sergey Berezovskiy Feb 24 '14 at 13:04
  • i read that before asking and didn't get it 100%. what made me hesitate is that I assign transaction to DbProviderConnection.Transaction in BeginTransaction. If it was just method returning the object I would have known that it's disposed. But it seems it makes no difference. – char m Feb 24 '14 at 13:07
  • @matti the only difference is that *resouce* variable is inaccessible in, and invisible to embedded statement. – Sergey Berezovskiy Feb 24 '14 at 13:10
11

From the specification:

8.13 The using statement

A using statement of the form

using (ResourceType resource = expression) statement

when ResourceType is a nullable value type or a reference type other than dynamic, the expansion is

{
    ResourceType resource = expression;
    try {
        statement;
    }
    finally {
        if (resource != null) ((IDisposable)resource).Dispose();
    }
}

A using statement of the form

using (expression) statement

has the same three possible expansions...The resource variable is inaccessible in, and invisible to, the embedded statement.

Therefore the object returned from cnctn.BeginTransaction() will be disposed when the block exits, but is not accessible inside the associated block.

Lee
  • 142,018
  • 20
  • 234
  • 287
4

Yeah, the Dispose will be called. the using statement only works with disposable objects. Like this:

using (DbProviderConnection cnctn = _planDb.CreateOpenConnection())
{
    using (cnctn.BeginTransaction())
    {
        // ...
        cnctn.Transaction.Commit();
    } // Here BeginTransaction.Dispose() is called.
} // Here DbProviderConnection.Dispose() is called.
Andre Kampling
  • 5,476
  • 2
  • 20
  • 47
Only a Curious Mind
  • 2,807
  • 23
  • 39
1

The object that BeginTransaction returns, is what will be disposed.

BeginTransaction returns a DbTransaction so that is what will be disposed

André Snede
  • 9,899
  • 7
  • 43
  • 67