Powershell 2.0 - закрытие SqlDataReader при передаче в функцию - PullRequest
4 голосов
/ 11 января 2011

Я взаимодействую с набором пользовательских сборок .Net 2.0, с Powershell 2.0, для автоматизации текущей задачи. Я загружаю все необходимые библиотеки DLL и вызываю метод DAL в библиотеке DLL для получения System.Data.SqlDataReader. Когда я передаю SqlDataReader в конструктор в той же пользовательской сборке, я получаю «Недопустимая попытка вызвать HasRows, когда читатель закрыт». исключение.

Пример кода:

dir D:\stuff\*.dll | foreach { [Reflection.Assembly]::LoadFrom($_.FullName) } | out-null
[CustomAssembly.DataConfig]::ConnectionString = "Valid Connection String"
$reader=[CustomAssembly.DAL.Thing]::Get(123)
new-object CustomAssembly.BusinessObjects.Thing($reader)

$ reader открыт и содержит данные, прежде чем я вызову конструктор Thing.

Должно быть, я что-то упустил, но я не уверен, что это такое.

Редактировать 1:

$ reader представляется прочитанным и закрытым каждый раз, когда он передается функции, в powershell или в сборке. Есть ли способ предотвратить это?

Редактировать 2:

Автоматическая развертка Powershell снова наносит удар

Как остановить PowerShell от распаковки объекта Enumerable?

Странное поведение в функции PowerShell, возвращающей DataSet / DataTable

Следующий измененный пример кода работает, заключая результат в массив из одного элемента, поэтому автоматическое развертывание не влияет на SqlDataReader. Обратите внимание на одну запятую после оператора "$ reader =". Это не опечатка.

dir D:\stuff\*.dll | foreach { [Reflection.Assembly]::LoadFrom($_.FullName) } | out-null
[CustomAssembly.DataConfig]::ConnectionString = "Valid Connection String"
$reader=,[CustomAssembly.DAL.Thing]::Get(123)
new-object CustomAssembly.BusinessObjects.Thing($reader)

1 Ответ

5 голосов
/ 11 января 2011

Я столкнулся с подобными проблемами некоторое время назад. Посмотрите на этот код:

Я создаю свой собственный перечислитель, который печатает некоторую информацию о том, когда он вызывается. Это то же самое, что ваш SqlDataReader, который (я думаю) также реализует IEnumerator.

PS> Add-Type -TypeDefinition @"
    using System;
    using System.Collections;
    public class MyEnumerator2 : IEnumerator
    {
        private int _count = 10;
        private Random r = new Random();

        public MyEnumerator2(int count)
        {
            _count = count;
        }

        public bool MoveNext()
        {
            Console.WriteLine("Moving!");
            _count--;
            return _count >= 0;
        }

        public void Reset()
        {
            throw new NotImplementedException();
        }

        public object Current
        {
            get
            {
                Console.WriteLine("Current!");
                return r.Next();
            }
        }
    }
"@

Тогда давайте создадим объект типа и попробуем вывести его:

PS> $mye = New-Object MyEnumerator2 5
PS> $mye | % -begin { write-host 'starting' } -Process { write-host 'next is ' $_ }
starting
Moving!
Current!
next is  2081278528
Moving!
Current!
next is  2000135673
Moving!
Current!
next is  692162542
Moving!
Current!
next is  1531746038
Moving!
Current!
next is  1550381634
Moving!

Все как и ожидалось. Но .. сейчас

PS> function iteratemye($o) {
    $o | % -begin { write-host 'starting' } -Process { write-host 'next is ' $_ }
}
PS> $mye = New-Object MyEnumerator2 5
PS> iteratemye $mye
Moving!
Current!
Moving!
Current!
Moving!
Current!
Moving!
Current!
Moving!
Current!
Moving!
starting
Moving!

Если вы передадите этот перечислитель в функцию, он прочитается до того, как он достигнет тела . Это очень плохо.

Итак, взгляните на ваш код. Если вы используете какую-то функцию, например, мой iteratemye, это является причиной ваших проблем.

Обновление: не реализовано IEnumerator, но IEnumerable. Я вижу, что вы просто передаете объект какому-то конструктору, что не является той же проблемой, с которой я столкнулся, но я считаю, что PowerShell все равно попытается получить перечислитель и поработать над магией.

...