Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Type de variable inattendu renvoyé par Receive-Job

  1. Existe-t-il un moyen d'obtenir le type de variable correct/attendu à renvoyer lors de l'appel de Receive-Job ?

En raison de l'utilisation d'une tâche en arrière-plan, vous perdez la fidélité du type  :les objets que vous récupérez sont des émulations sans méthode des types d'origine.

Recréer manuellement les types d'origine n'en vaut pas la peine et peut même ne pas être possible - bien que peut-être que travailler avec les émulations soit suffisant.

Mettre à jour  :Selon votre propre réponse, passer du travail avec System.DataSet à System.DataTable a abouti à des émulations utilisables pour vous.

Voir la section du bas pour plus d'informations.

  1. Existe-t-il un meilleur moyen d'exécuter des requêtes SQL sous un autre compte AD, à l'aide de la commande Invoke-Sqlcmd ?

Vous avez besoin d'un en cours méthode d'invocation afin de maintenir la fidélité du type , mais je ne pense pas que ce soit possible avec des commandes arbitraires si vous voulez usurper l'identité d'un autre utilisateur .

Par exemple, l'alternative in-process (basée sur les threads) à Start-Job - Start-ThreadJob - n'a pas de -Credential paramètre.

Votre meilleur pari est donc d'essayer de faire Invoke-SqlCmd -Credential de paramètre fonctionne pour vous ou trouvez une autre manière d'exécuter vos requêtes avec les informations d'identification d'un utilisateur donné.

Sérialisation et désérialisation d'objets en background jobs / remoting / mini-shells :

Chaque fois que PowerShell rassemble des objets au-delà des limites de processus , il utilise la sérialisation basée sur XML à la source, et désérialisation à destination , en utilisant un format appelé CLI XML (Common Language Infrastructure XML).

Cela se produit dans le contexte de la communication à distance PowerShell (par exemple, Invoke-Command appelle avec le
-ComputerName paramètre) ainsi que dans les tâches en arrière-plan (Start-Job ) et les soi-disant mini-shells (qui sont implicitement utilisés lorsque vous appelez la CLI PowerShell depuis PowerShell lui-même avec un bloc de script; par exemple, powershell.exe { Get-Item / } ).

Cette désérialisation maintient la fidélité du type uniquement pour un ensemble limité de types connus , comme spécifié dans MS-PSRP, la spécification du protocole de communication à distance PowerShell. Autrement dit, seules les instances d'un ensemble fixe de types sont désérialisées comme leur type d'origine .

Les instances de tous les autres types sont émulées :les types de type liste deviennent [System.Collections.ArrayList] instances, les types de dictionnaire deviennent [hasthable] les instances et les autres types deviennent des objets personnalisés sans méthode (propriétés uniquement) ([pscustomobject] cas) , dont .pstypenames propriété contient le nom du type d'origine préfixé par Deserialized. (par exemple, Deserialized.System.Data.DataTable ), ainsi que les noms préfixés de la base du type types (hiérarchie d'héritage).

De plus, la profondeur de récursivité pour les graphes d'objets de non -[pscustomobject] instances est limité à 1 niveau - notez que cela inclut l'instance de classes personnalisées PowerShell , créé avec la class mot-clé :c'est-à-dire si les valeurs de propriété d'un objet d'entrée ne sont pas elles-mêmes des instances de types bien connus (ce dernier inclut les types à valeur unique, y compris les types primitifs .NET tels que [int] , par opposition aux types composés de plusieurs propriétés), ils sont remplacés par leur .ToString() représentations (par exemple, tapez System.IO.DirectoryInfo a un .Parent propriété qui est un autre System.IO.DirectoryInfo instance, ce qui signifie que le .Parent la valeur de la propriété est sérialisée en tant que .ToString() représentation de cette instance, qui est sa chaîne de chemin d'accès complète) ; en bref :Les objets non personnalisés (scalaires) sont sérialisés de sorte que les valeurs de propriété qui ne sont pas elles-mêmes des instances de types connus sont remplacées par leur .ToString() représentation ; voir cette réponse pour un exemple concret.
En revanche, explicite utilisation de la sérialisation CLI XML via Export-Clixml par défaut à une profondeur de 2 (vous pouvez spécifier une profondeur personnalisée via -Depth et vous pouvez également contrôler la profondeur si vous utilisez le sous-jacent System.Management.Automation.PSSerializer tapez directement ).

Selon le type d'origine, vous pouvez être capable de reconstruire des instances du type d'origine manuellement , mais cela n'est pas garanti. (Vous pouvez obtenir le nom complet du type d'origine en appelant .pstypenames[0] -replace '^Deserialized\.' sur un objet personnalisé donné.)

Cependant, selon vos besoins de traitement, les émulations des objets d'origine peut suffire.