PowerShell und DataTable

Auf der Seite PS CSV-Datei habe ich schon ausgeführt, wie man mit CSV-Dateien kleine Datenbanken im Speicher halten kann. Aber optimal ist das ganze natürlich nicht. Vor allem gibt es keine echte Typisierung der Felder, keine Prüfung der Eindeutigkeit und vieles mehr. Es ist beim besten Willen keine Datenbank. Auf dieser Seite möchte ich nun nicht vorstelle, wie sie eine Datenbanktabelle auf einem SQL-Server oder eine lokale (ODBC-Datenbank) als Datei speichern. Die meisten PowerShell-Skripte möchten vielleicht Ergebnisse im Speicher strukturiert ablegen, um immer wieder schnell auf diese zuzugreifen oder am Ende diese sauber abspeichern zu können. Und dazu eignet sich die .NET-Klasse "System.Data.DataTable" sehr gut.

Instanzieren der System.Data.DataTable

Ehe Sie Werte ablegen können, müssen Sie die Tabelle erst einmal aufbauen. Das sieht auf den ersten Blick etwas umfangreicher aus, aber ist doch einfach zu verstehen.

# Die Tabelle wird instanziert und mit einem Namen versehen
$table = New-Object system.Data.DataTable 'IISUsage'

#Nun werden die Spalten addiert
$newcol = New-Object system.Data.DataColumn Vorname,([string]); $table.columns.add($newcol)
$newcol = New-Object system.Data.DataColumn Nachname,([string]); $table.columns.add($newcol)
$newcol = New-Object system.Data.DataColumn Alter,([long]); $table.columns.add($newcol)

# Anzeige der Einstellungen
$table.Columns | ft -AutoSize

AllowDBNull AutoIncrement AutoIncrementSeed AutoIncrementStep Caption  ColumnName Prefix DataType          DateTimeMode DefaultVa
                                                                                                                        lue
----------- ------------- ----------------- ----------------- -------  ---------- ------ --------          ------------ ---------
       True         False                 0                 1 Vorname  Vorname           System.String unspecifiedLocal
       True         False                 0                 1 Nachname Nachname          System.String unspecifiedLocal
       True         False                 0                 1 Alter    Alter             System.Int64 unspecifiedLocal

So eine Zeile hat Natürlich noch einige Properties mehr:

PS C:\inetpub\logs\LogFiles\W3SVC1> $table.Columns.Item("Vorname")


AllowDBNull        : True
AutoIncrement      : False
AutoIncrementSeed  : 0
AutoIncrementStep  : 1
Caption            : Vorname
ColumnName         : Vorname
Prefix             :
DataType           : System.String
DateTimeMode       : unspecifiedLocal
DefaultValue       :
Expression         :
ExtendedProperties : {}
MaxLength          : -1
Namespace          :
Ordinal            : 0
ReadOnly           : False
Table              : {} unique             : False
ColumnMapping      : Element
Site               :
Container          :
DesignMode         : False

Diese Einstellungen gehen also auf jeden Fall weiter als die einfache CSV-Tabelle von PS CSV-Datei.

Daten addieren

Nun wollen wir auch hier Zeilen addieren:

# Befuellen mit Musterdaten
1..5 | %{
   $row = $table.NewRow()
   $row.Vorname= ("Vorname"+$_)
   $row.Nachname= ("Nachname"+$_)
   $row.Alter= [int]($_)
   $table.Rows.Add($row) 
}

# Ausgabe
$table.Rows

Vorname                                     Nachname                                   Alter
-------                                     --------                                   -----
Vorname1                                    Nachname1                                  1
Vorname2                                    Nachname2                                  2
Vorname3                                    Nachname3                                  3
Vorname4                                    Nachname4                                  4
Vorname5                                    Nachname5                                  5

Suchen und Ändern

Eine Datenbank ist natürlich nichts wert, wenn man keinen wahlfreien Zugriff auf die Daten hat und Inhalte nicht auch ändern könnte. Das geht mit den Tabellen natürlich auch.

#Suche Zeilen mit Nachname4
$ergebnis = $table.Select("Nachname= 'Nachname4'")

# Ausgabe ergebnis
$ergebnis
Vorname                                     Nachname                                   Alter
------                                     --------                                   -----
Vorname4                                    Nachname4                                  4

Zugriff auf Werte ist lesend undschreiben möglich. Achten Sie auch hier darauf, dass das Ergebnis mehrere Zeilen haben kann. Interessant ist aber hier im Gegensatz zur CSV-Datei die Typisierung der Felder

$ergebnis[0].alter.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int64                                    System.ValueType

Hier kann man also direkt mit Zahlen rechnen

# 99 addieren
$ergebnis[0].alter +=99

#ergebnis anzeigen
$ergebnis[0].alter
103

Auch hier wirkt die Änderung direkt auf das Quellobjekt durch:

PS C:\inetpub\logs\LogFiles\W3SVC1> $table.rows | ft

Vorname                                     Nachname                                   Alter
-------                                     --------                                   -----
Vorname1                                    Nachname1                                  1
Vorname2                                    Nachname2                                  2
Vorname3                                    Nachname3                                  3
Vorname4                                    Nachname4                                  103
Vorname5                                    Nachname5                                  5

Export und Import

Wenn Sie die Typisierung später nicht mehr benötigen, dann können Sie natürlich wieder mit Export-CSV die Tabelle einfach als Liste ausgeben:

#
$table | export-csv table.csv

# Anzeige
get-content table.csv
#TYPE System.Data.DataRow
"Vorname","Nachname","Alter"
"Vorname1","Nachname1","1"
"Vorname2","Nachname2","2"
"Vorname3","Nachname3","3"
"Vorname4","Nachname4","103"
"Vorname5","Nachname5","5"

Der Export ohne "-NoTypeInformation" bringt keinen Vorteil beim Import-CSV. Die Datenbankinformation über Typisierung etc. geht verloren. Aber die Information geht auch verloren, wenn Sie mit Export-CliXML und Import-CliXML arbeiten. Diese Datenbanktabelle im Speicher ist also nur etwas für den temporären Gebrauch.

Weitere Links