вернуть заявление изнутри, используя - PullRequest
2 голосов
/ 21 апреля 2010
  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();
         }

Это возвращает IEnumerable DataRow. Вопрос заключается в том, что поскольку возвращение находится в операторе using, будет ли свойство распоряжаться IDBCommand? Я знаю, что могу легко это изменить, поэтому я изменяю область действия DataSet вне использования, но это больше удивительно, чем что-либо еще.

Ответы [ 4 ]

4 голосов
/ 21 апреля 2010

Да, это будет работать, как и ожидалось, при правильной утилизации IDbCommand.Компилятор преобразует блок using в try-catch-finally, где Dispose вызывается в блоке finally.

2 голосов
/ 11 августа 2011

IDbCommand расположен правильно. Как правило, при возврате из оператора using вы можете это сделать, если:

  1. То, что вы возвращаете, не входит в пункт об использовании Заявление
  2. Возвращаемая вещь не является ссылкой, созданной в блоке оператора using.

В первом случае оператор using избавится от того, что вы пытаетесь вернуть, а во втором случае переменная выйдет из области видимости.

1012 *, например *

//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;
     }
}

Здесь утверждение using(){ ... } - наш друг. Когда мы выходим из блока, наш SmtpClient удаляется, и результирующее условие все еще будет существовать для использования вами.

Однако, скажем, мы пишем приложение WinForm или приложение WPF и оборачиваем блок using вокруг нашего контекста данных, а затем создаем проблему, поскольку контекст исчезает, прежде чем элемент управления сможет его использовать.

// 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;
}

Здесь заявление using(){ ... } причиняет нам боль. Как и в случае, когда мы обращаемся к dataBind нашего клиента к GridView (или другому такому элементу управления, связанному с данными), тот факт, что мы избавились от DbContext, будет означать, что нашей форме нечего связывать, поэтому она выдаст исключение!

НТН

2 голосов
/ 21 апреля 2010

Да, команда DB будет располагаться, пока все хорошо.

Вы можете получить проблемы с IEnumerables. Потому что элементы могут потенциально создаваться при получении их из IEnumerable, а не при создании IEnumerable, такова его природа. Так что это зависит от того, как реализовано ds.Tables[0].AsEnumerable(). Он может ждать выполнения команды, пока вы не получите первый элемент. Это в коде вызова, вне блока использования. Вы получите ошибку, потому что команда была удалена.

Это, вероятно, не проблема здесь, но всегда следует учитывать при возврате IEnumerables (или лямбда-выражений) из блока using:

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

При доступе к первому элементу, a уже уничтожен, и вы получаете ошибку.

0 голосов
/ 21 апреля 2010

Область действия вашего IDbCommand объекта очень ясна: между скобками { и }. Как только ваш программный поток завершается, объект удаляется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...