2011-01-11 11 views
4

Ich arbeite mit einer Reihe benutzerdefinierter .NET 2.0-Assemblys mit Powershell 2.0 zusammen, um eine aktuelle Aufgabe zu automatisieren. Ich lade alle erforderlichen DLLs und rufe eine DAL-Methode in der DLL auf, um einen System.Data.SqlDataReader abzurufen. Wenn ich den SqlDataReader in einem Konstruktor in derselben benutzerdefinierten Assembly übergebe, erhalte ich einen "ungültigen Versuch, HasRows aufzurufen, wenn der Reader geschlossen ist". Ausnahme.Powershell 2.0 - SqlDataReader schließt bei Übergabe an eine Funktion

Codebeispiel:

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) 

Die $ Leser ist offen und hat Daten, bevor ich die Sache Konstruktor aufrufen.

Ich muss etwas vermissen, aber ich bin mir nicht sicher, was es ist.

Edit 1:

$ Leser scheint zu lesen, und geschlossen wird, jederzeit an eine Funktion übergeben wird, in Powershell oder in einer Baugruppe. Gibt es einen Weg dies zu verhindern?

Edit 2:

Powershell automatisches Abrollen schlägt wieder

How to stop PowerShell from unpacking an Enumerable object?

Strange behavior in PowerShell function returning DataSet/DataTable

Das folgende modifizierten Codebeispiel funktioniert, indem das Ergebnis in einem einzigen Elementanordnung Einwickeln, so die Das automatische Ausrollen wirkt sich nicht auf den SqlDataReader aus. Beachten Sie das einfache Komma nach der Anweisung "$ reader =". Das ist kein Tippfehler.

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) 

Antwort

5

Ich stieß auf ähnliche Probleme vor einiger Zeit. Schau dir diesen Code an:

Ich erstelle meinen eigenen Enumerator, der einige Informationen darüber ausgibt, wann er aufgerufen wird. Es ist das gleiche wie Ihre SqlDataReader, die (glaube ich) auch IEnumerator implementiert.

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(); 
      } 
     } 
    } 
"@ 

Dann lassen Sie sich ein Objekt des Typs erstellen und versuchen, es zu Ausgabe:

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! 

Alles ist wie erwartet. Aber .. jetzt

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! 

Wenn Sie diesen enumerator an eine Funktion übergeben, wird es lesen, bevor sie den Körper erreicht. Das ist sehr schlecht.

Also schauen Sie sich Ihren Code an. Wenn Sie eine Funktion wie meine iteratemye verwenden, ist das die Ursache Ihrer Probleme.

Update: Es implementiert IEnumerator, aber IEnumerable nicht. Ich sehe, dass Sie nur das Objekt an einen Konstruktor übergeben, was nicht das gleiche Problem ist, das ich hatte, aber ich glaube, PowerShell wird immer noch versuchen, Enumerator zu bekommen und etwas Magie zu tun.

+0

Das scheint mit dem SqlDataReader der Fall zu sein. Gibt es eine Möglichkeit, das zu verhindern? – Jared314

+0

Sieht so aus, als müsste ich es in ein anderes Array einpacken, weil es keine Möglichkeit gibt, das zu verhindern. – Jared314

Verwandte Themen