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
- PS CSV-Datei
- DataColumn Constructor
http://msdn.microsoft.com/en-us/library/system.data.datacolumn.datacolumn.aspx - DataTable.Select Method
http://msdn.microsoft.com/de-de/library/h71xaeh0.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1