Return from within using

  using (IDbCommand command = new SqlCommand())
         {
             IDbDataAdapter adapter = new SqlDataAdapter();
             DataSet ds = new DataSet();
             adapter.SelectCommand = command;
             command.Connection = _dataAccess.Connection;
             command.CommandType = CommandType.StoredProcedure;
             command.CommandText = "GetProcData";
             command.Parameters.Add(new SqlParameter("@ProcID  ", procId));

            adapter.Fill(ds);
            return ds.Tables[0].AsEnumerable();
         }

      

This returns IEnumerable DataRow. The question is, since the return is in a using statement, will it have an IDBCommand property? I know I can refactor this easily, so I change the scope of the DataSet outside of use, but this is more of a miracle than anything else.

+2


a source to share


4 answers


Yes, this will work as expected when IDbCommand

positioned correctly. The compiler converts the used block to try-catch-finally

where it Dispose

is called in the block finally

.



+4


a source


Yes, the DB command will be removed as long as it's that good.

You may get problems with IEnumerables. Since elements can be instantiated by getting them from an IEnumerable and not by creating an IEnumerable, that's the nature of it. So it depends on how it is ds.Tables[0].AsEnumerable()

implemented. It can wait for the command to complete until you get the first item. This is in the calling code, outside the used block. You will get an error because the command has been removed.

This is probably not a problem, but should always be considered when returning IEnumerables (or lambda expressions) from a use block:



using (A a = new A())
{
  return someItems.Select(x => a.Get(x));
}

      

When accessing the first item is a

already set and you get an error.

+2


a source


IDbCommand

is positioned correctly. Typically, when you return from a using statement, you can do this as long as:

  • What you are returning is not covered by the item of use Statement
  • The thing returned is not a reference created in a using statement block.

In the first case, the using statement will get rid of the thing you are trying to return, and in the second case, the variable will go out of scope.

eg.

//this is fine as result is createsd outside the scope of the block. 
bool result = false;
using (SmtpClient mailClient = new SmtpClient())
{
    try
    {
        mailClient.Send(...);
        result = true;
     } 
     catch(SmtpException)
     {
         result = false;
     } 
     finally 
     {
         return result;
     }
}

      

Here the operator using(){ ... }

is our friend. When we exit the block, ours SmtpClient

is positioned and the result condition will exist for you.

However, let's say we are writing a WinForm app or WPF app and we wrap a use block around our data context, then we create a problem as the context disappears before the control can use it.

// this will fail when you bind the customers to a form control!
using (DbContext context = new DBContext())
{
context.Customers.Where(c => c.Name.Contains("Bob")).Load();
return context.Customers.Local;
}

      

Here the expression using(){ ... }

hurts us. How and when we come to dataBind our client to a GridView (or some other similar data binding control), the fact that we have disposed of DbContext

will mean that our form has nothing to do with it, so it will throw an exception!

NTN

+2


a source


The scope of your object is IDbCommand

very simple: between the brackets {

and }

. As soon as your program flow exits from there, the object will be deleted.

0


a source







All Articles