söndag, januari 28, 2007

PowerShellProvider

Jag har nu skapat en PowerShellProvider. Man skulle kunna jämföra det med ett virtuellt filsystem för PowerShell. Redan från början innehåller PowerShell ett antal providers:
PS F:\/> Get-PSProvider

Name Drives
---- ------
Alias {Alias}
Environment {Env}
FileSystem {C, E, F, D...}
Function {Function}
Registry {HKLM, HKCU}
Variable {Variable}
Certificate {cert}

Som t.ex. Registry innehåller ju då naturligtvis registret, och man kan då komma åt registret med samma kommando som man är van att använda på filsystemet. Dir för att visa innehållet, cd för att navigera i strukturen mm. Dir t.ex. är ett alias för cmdlet:en Get-ChildItem och cd är ett alias för Set-Location.

Jag skapade MyProvider som ärvde av NavigationCmdletProvider, överlagrade följande funktioner:
  • InitializeDefaultDrives
  • NormalizeRelativePath
  • GetChildItems
  • IsItemContainer
  • GetItem
Jag hade då skapat ett standard interface in mot applikationen.
Kunde navigera bland applikationens objekt med cd och titta på dem med dir. Jag kan tilldela ett av applikationens objekt till en PowerShell-variabel och komma åt värden på t.ex. Properties.
Jag läste sedan om PowerGadgets, en samling datavisualiseringskomponenter, som visarinstrument, diagram o.dyl. och plötsligt kunde jag enkelt visa egenskaper i mitt program med standardkomponenter. Dessutom kan jag naturligtvis skriva skript som interagerar med mitt program.

Jag gjorde följande:
cd MyProvider:
$s = Get-Item "Server 1/System/Time/Second"
$s.Attributes[3].ClrValue | Out-Gauge

Out-Gauge är en cmdlet i PowerGadgets som nu visade värdet av en property i objektet Second. Det fjärde attributet (
Attributes[3]) som råkar vara aktuell sekund uvarande minut.

Där finns mer att göra, implementera kopiering, radering, skapa nya objekt. Men inte heller det verkar vara mycket jobb. Mer om hur man skapar interface mot PowerShell

En intressant artikel om datadrivna tester med Excel och PowerShell

söndag, januari 14, 2007

Kompakta databaser i .NET

Till sist kom jag till skott med att testa SQLite. System.Data.SQLite var en trevlig bekanskap. Det är en ADO .NET 2.0 databasprovider för SQLite, med själva SQLitemotorn inbyggd. Man har tagit C-källkoden från standard SQLite och byggt med den i assemblyt. Den kommer i versioner för ARM processorer - dvs Compact Framework - Itanium, X64 och den gamla hederliga x86.
Jag roade mig med att jämföra lagringsutrymmet som krävdes för en SQLite-databas och en motsvarande för SQL Server 2005 Compact, utrymmesmässigt vann SQLite.
Jag har utökat mina magra SQLkunskaper lite de senaste dagarna, men jag är fortfarande en nybörjare på området.
Jag hade en tabell med tre kolumner:
CREATE TABLE TestTable (Id INTEGER PRIMARY KEY AUTOINCREMENT, Time DATETIME, Value BIGINT)
Tabellen för
SQL Server 2005 Compact skapade jag med designern i VS 2005 och sen försökte jag göra samma sak med kod för SQLite. Jag fick fram en tabell, men det visade sig att SQLite inte hade en egentlig kolumntyp för DateTime, men det kan hanteras, och BIGINT bluffade den lite med också.
Jag antog att detta skulle ta åtminstone 4 + 8 + 8 byte. För SQLite tog det ca 22 byte per record och för SQL Server 2005 Compact tog det mellan 29 och 45 byte per record, beroende på vilka properties jag valde på id-kolumnen, om den skulle vara unik, identity etc. Jag körde testet på min bärbara i Vista, och första testet att lägga in 100 000 rader med standardinställningar och utan transaktioner, då var SQL Server 2005 Compact 100-tals gånger snabbare.
Det gjorde mig lite orolig. Men eftersom jag den här gången var ute efter en utrymmessnål databas som dessutom kunde användas i Linux, så gick mina tester vidare med enbart SQLite, och genom att gruppera mina inserts i transaktioner och på så sätt ge databasen tillåtelse att inte skriva varje ändring direkt till disk så blev mina testprestanda även med SQLite 100-tals gånger bättre. Jag tror att jag skapade 100 000 rader jag skapade vid det tillfället, men utan transaktioner tog det ca 14 minuter och med tog det bara några få sekunder.

Jag lärde mig även att SQLite är en lite annorlunda databas, som kan tillåta att man lagrar olika typer av data i samma kolumn. Den har bara följande lagringstyper:

  • NULL.
  • INTEGER. lagras i 1 till 8 byte beroende på storleken på talet.
  • REAL. flyttal 8-byte IEEE.
  • TEXT. Textsträng, lagring enligt inställning för databasen (UTF-8, UTF-16BE or UTF-16-LE). Jag rekommenderar UTF-8.
  • BLOB.

Detta var ju lite av förklaringen till varför SQLite var så snål i jämförelse med SQL Server 2005 Compact, eftersom många av mina testvärden var små heltal, Den senare jobbar förmodligen med fasta storlekar på fälten. Och det bör kunna ge bättre prestanda vid uppdateringar antar jag.
Kolumnerna i SQLite kan sedan vara av typen:
  • TEXT
  • NUMERIC
  • INTEGER
  • REAL
  • NONE
Om man väljer Numeric så försöker databasmotorn först att tolka värdet som en int eller real, om inte det går så lagras värdet som text. Med None är tolkningen ännu mer liberal den gör så gott den kan även när det gäller NULL- och BLOB-värden. Jag testade att lagra heltal, flyttal och text i samma kolumn. Det fungerade men Query Analyzern SQLiteQA3 blev lite förvirrad. Om första raden i tabellen innehöll ett heltal, så försökte den tolka övriga rader som heltal också. Vilket omvandlade "Kalle Kula" till en simpel nolla :o)
men följande kod fick jag ut de rätta värdena:

m_Cmd.CommandText = String.Format("SELECT Id, Value FROM [{0}]", TrendName);
SQLiteDataReader reader = m_Cmd.ExecuteReader();
while (reader.Read())
{
object id = reader.GetValue(0);
object value = reader.GetValue(1);
Console.WriteLine(id.ToString() + value.ToString());
}
m_Connection.Close();
Jag ändrade föresten min tabellskaparkod till:
m_Cmd.CommandText = String.Format("CREATE TABLE {0} (Id INTEGER PRIMARY KEY, Time INTEGER, Value NONE)", TrendName);
Sen skapade jag en trigger för att begränsa storleken på mina tabeller, men det får jag skriva om en annan dag.
Det är trevligt att Microsoft lyssnade på sina kunder och gav oss rätten att distribuera SQL Server 2005 Compact, så att man kan använda samma databaskod i sin desktopapplikation som i den tillhörande Compact Frameworklösningen, detta och möjligheten att installera med click once, är ju möjligheter som gäller för båda de nämnda databaserna. Det finns mycket mer att säga. Det finns uppenbara fördelar med båda databaserna, men nu börjar mina ögonlock att bli tunga. Så är det någon som undrar mer om det så skriv en kommentar. Godnatt.