Powershell 2.0 - 传递给函数时关闭SqlDataReader

时间:2011-01-11 14:24:37

标签: powershell powershell-v2.0 sqldatareader

我正在使用Powershell 2.0与一组自定义.Net 2.0程序集进行交互,以自动执行当前任务。我加载所有必需的dll并在dll中调用DAL方法来检索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)

在我调用Thing构造函数之前,$ reader是打开的,并且有数据。

我必须遗漏一些东西,但我不确定它是什么。

修改1:

$ reader无论何时传递给函数,PowerShell或程序集中,都会被读取并关闭。有办法防止这种情况吗?

编辑2:

Powershell自动展开再次打击

How to stop PowerShell from unpacking an Enumerable object?

Strange behavior in PowerShell function returning 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 个答案:

答案 0 :(得分:5)

前段时间我遇到过类似的问题。看看这段代码:

我创建了自己的Enumerator,它会打印一些有关何时调用它的信息。它与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仍然会尝试获取枚举器并做一些魔术。