Donnerstag, 30. Juni 2011

Microsoft SQL-Server Verbindungsserver einrichten

Mit folgendem, simplen SQL-Statement würde man Daten der Tabelle "Maschinen" aus der Datenbank "FlorianTestDB" von einem Server "Testserver2" auf einen anderen Server "Testserver1" in die gleichnamige Datenbank/Tabelle kopieren.

INSERT INTO [Testserver1].[FlorianTestDB].[dbo].[Maschinen]
SELECT * FROM [Testserver2].[FlorianTestDB].[dbo].[Maschinen]
GO

Voraussetzung für eine erfolgreiche Übertragung ist, dass der Zielserver als sogenannter Verbindungsserver auf dem Quellserver eingerichtet ist. Ist dieses nicht der Fall, so kommt folgende Meldung.

Meldung 7202, Ebene 11, Status 2, Zeile 1
Server 'Testserver1' konnte in 'sys.servers' nicht gefunden werden. Stellen Sie sicher, dass der richtige Servername angegeben wurde. Führen Sie ggf. die gespeicherte Prozedur 'sp_addlinkedserver' aus, um den Server in 'sys.servers' hinzuzufügen.

Abhilfe schafft man, indem man den Verbindungsserver auf einfache Art und Weise  anlegt. Hierzu muss man eine Verbindung mit dem Quellserver herstellen und folgenden Befehl ausführen, um den Zielserver als Verbindungsserver einzurichten.

EXEC sp_addlinkedserver 'Testserver1'
GO

Als Ergebnis sollte folgendes zurückkommen.

Befehl(e) wurde(n) erfolgreich abgeschlossen.

Führt man das SQL-Statement zum Kopieren der Daten nun erneut aus, so sollte es erfolgreich ausgeführt werden.

Eine kleine Einschränkung hierbei gibt es jedoch. Fügt man den Verbindungsserver wie oben beschrieben hinzu, so ist es notwendig, dass auf beiden Servern der aktuell verwendete Benutzer identisch eingerichtet ist.

Möchte man dieses nicht, benutzt unterschiedliche Passwörter oder verschiedene Benutzer, so ist es am einfachsten den Verbindungsserver über das SQL-Server-Management-Studio anzulegen.

Diese Vorgehensweise geht für die SQL-Server-Versionen 2000, 2005 und 2008

Dienstag, 28. Juni 2011

Dateidownload via REST-Webservice

REST ist ein Akronym für Representational State Transfer. Einfach gesagt steht REST für eine Art der Datenübertragung per HTTP.  Unterhalb von REST gibt es noch eine weitere Unterscheidung je nach Befehlstyp. Hier gibt es folgende Möglichkeiten:

- GET (Download von Dateien)
- POST (Upload von Dateien)
- PUT (Upload von Dateien)
- DELETE (Löschen von Dateien)

Im folgenden Beispiel zeige ich, wie man einen einfachen Datei-Download anhand eines REST-Webservices (per GET) erstellen kann.

Bei "context" handelt es sich um den aktuellen HttpContext.

// Prüfen der Http-Übertragungsmethode
if(context.Request.HttpMethod = "GET")
{
    // FileInfo-Objekt für die Datei erstellen, die heruntergeladen werden soll
    FileInfo requestFile = new FileInfo("C:\\Testdatei.txt");

    // Anhand der gerade ermittelten Datei ein ByteArray für eine Datenübertragung erstellen
    byte[] fileBytes = File.ReadAllBytes(requestFile.FullName);

    // Aktuellen Inhalt des HttpContextes leeren
    context.Response.Clear();

    // Aktuelle Headerinformationen des HttpContextes leeren
    context.Response.ClearHeaders();

    // Angabe des Types der zu übertragenden Datei 
    context.Response.ContentType = "text/plain";

    // Neue Headerinformationen zum HttpContext hinzufügen
    context.Response.AddHeader("Content-Disposition", "attachment; filename=\"" + requestFile.Name + "\"");
    context.Response.AddHeader("Content-Length", requestFile.Length.ToString());
    
    // MD5-Hash für aktuelle Datei erstellen um nach dem Download die Vollständigkeit zu prüfen
    // Info: FileHelper ist eine eigene Hilfs-Klasse zum erstellen des MD5-Hash (siehe ältere Blogposts)
    context.Response.AddHeader("Content-MD5", StringHelper.Base64Encode(FileHelper.GetMD5Hash(requestFile.FullName)));
    
    // Die Datei/ByteArray ausgeben bzw. zum Download anbieten
    context.Response.OutputStream.Write(fileBytes, 0, fileBytes.Length);
    
    // HttpResponse wieder freigeben
    context.Response.Flush();

    // HttpResponse beenden
    context.Response.End();
}

Montag, 27. Juni 2011

MD5-Hash einer Datei erstellen

Wenn man mit Dateien arbeitet speziell im Bereich Download/Upload, muss man immer wieder Dateien auf Vollständigkeit prüfen. Dieses kann man am besten über einen MD5-Hash machen.
Erstellt man einen MD5-Hash der Ursprungsdatei kann man diesen mit dem der neu erstellten Datei vergleichen um zu prüfen, ob die Dateien übereinstimmen. Ist das nicht der Fall, so ist beim Download/Upload etwas schief gelaufen.

Einen MD5-Hash kann man ganz einfach wie folgt erstellen.

// Gibt einen MD5-Hash-String für eine Datei zurück
public static string GetMd5HashString(string filePath)
{
     // Datei in neues FileStream-Objekt einlesen
     FileStream fileStream = new FileStream(filePath, FileMode.Open);

     // Neues Objekt für MD5-Kryptographi-Provider erstellen
     MD5 md5 = new MD5CryptoServiceProvider();

     // ByteArray mit MD5-Hash der eingelesenen Datei erstellen
     byte[] fileHash = md5.ComputeHash(fileStream);

     // FileStream mit eingelesener Datei wieder schließen
     fileStream.Close();

     // StringBuilder-Objekt erstellen um anschließend den MD5-Hash als String zu speichern
     StringBuilder sb = new StringBuilder();

     // MD5-Hash (ByteArray) byteweise verarbeiten und an StringBuilder anhängen
     for (int i = 0; i < fileHash.Length; i++)
     {
          sb.Append(fileHash[i].ToString("x2"));
     }

     // MD5-Hash als String ausgeben
     return sb.ToString();
}

Freitag, 24. Juni 2011

Installierte Versionen des .Net-Framework ermitteln unter Windows Mobile

Heute hatte ich das Problem, dass ich eine kleine Testanwendung schreiben wollte die auf einem Windows Mobile und einem Windows CE Gerät laufen sollte. Einzige Voraussetzung war, dass kein neues .Net Framework bzw. Compact Framework installiert werden darf.

Da es sich bei dem einen Gerät um das Betriebssystem Windows CE 5.0 handelt, kommen für die Entwicklung erst einmal 2 Framework-Versionen in Frage. Und zwar hat die Version 5.0 standardmäßig das .Net-Framework 1.0 installiert. Handelt es sich jedoch um die Version 5.0 mit installiertem Service Pack 2, so ist auch das .Net-Framework 2.0 eingerichtet.

Wie bekommt man nur einfach raus, welches das aktuell höchste, vorhandene .Net-Framework ist.
Hierzu gibt es eigentlich zwei ganz einfache Methoden.

1. Im Windows-Verzeichnis befindet sich eine Datei mit dem Namen "cgacutil.exe". Wenn man diese einfach ausführt, bekommt man alle installierten .Net-Frameworks, sortiert von alt nach neu, aufgelistet.
Der letzte Eintrag ist also die höchste installierte Version.

2. Sollte die unter Punkt 1 beschriebene Datei aus irgendwelchen Gründen nicht aufrufbar sein, so kann man sich auch einen Registry-Editor zur Hilfe ziehen. Diesen installiert man auf dem PC und greift von dort aus auf das angeschlossene mobile Gerät zu.
Aus dem Editor geht man dann in der Registry unter folgenden Eintrag:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP
Hier werden alle installierten Versionen des .Net-Frameworks in Unterverzeichnissen aufgelistet.

Mittwoch, 22. Juni 2011

Zugriff aus .Net auf SQLite Datenbanken

In meinem letzten Beitrag habe ich mich ja mit einem universellen Datenbank-Browser für Mac OS und Windows beschäftigt. Dieses war mir auch sehr wichtig, da man so recht schnell Datenbanken erstellen, mit ersten Testdaten füllen und später die richtigen Daten gut prüfen kann.

Jetzt möchte ich aber den eigentlich interessanteren Teil ansprechen. Den Datenzugriff aus .Net auf eine SQLite-Datenbank.

In folgendem Beispiel möchte ich zeigen, wie man per C#-Code eine SQLite-Datenbank erstellt, eine Tabelle anlegt und diese mit Daten befüllt.


// Datenbanknamen angeben
string dataBaseName = "Maschinen.db";

// Connection-Objekt instanziieren
SQLiteConnection connection = new SQLiteConnection();

// Datenbankdatei erstellen (inkl. Standarddatenbank "main")
SQLiteConnection.CreateFile(dataBaseName);

// Connection-String für die Verbindung erstellen
connection.ConnectionString = "Data Source=" + dataBaseName;

// Verbindung zur Datenbank erstellen
connection.Open();

// Command-Objekt instanziieren um SQL-Statements auszuführen
SQLiteCommand command = new SQLiteCommand(connection);

// SQL-Statement ohne Parameter erstellen und ausführen
command.CommandText = "CREATE TABLE Maschinen(Id INTEGER PRIMARY KEY, Name VARCHAR(255), Typ VARCHAR(255));";
command.ExecuteNonQuery();

// SQL-Statement mit Parametern erstellen
command.CommandText = "INSERT INTO Maschinen VALUES (@Id, @Name, @Typ);";

// Command-Objekt mit Parametern füllen
command.Parameters.Add(new SQLiteParameter("@Id", 1));
command.Parameters.Add(new SQLiteParameter("@Name", "Maschine1"));
command.Parameters.Add(new SQLiteParameter("@Typ", "Typ1"));

// SQL-Statement mit Parametern ausführen
command.ExecuteNonQuery();

// Parameter aus Command-Objekt wieder entfernen
command.Parameters.Clear();

// Command-Objekt wieder freigeben
command.Dispose();

// Verbindung zur Datenbank schliessen
connection.Close();

Dienstag, 21. Juni 2011

SQLite Datenbank-Browser für Mac und Windows

Da ich momentan viel parallel mit Windows und Mac OS arbeite und auch bei kleineren Projekten oft SQLite-Datenbanken verwende, habe ich einen Datenbank-Browser gesucht, der unter beiden Plattformen läuft.

Bei der Suche bin ich über interessante Clients gestolpert, die auch wirklich gut waren. Viele sind aber entweder für Mac OS oder für Windows gewesen. Letztendlich bin ich bei einen Open Source Tool hängen geblieben. Dieses trägt den Namen "SQLite Database Browser" und ist zu finden unter folgendem Link.
http://sqlitebrowser.sourceforge.net/

SQLite Database Browser unter Mac OS

Dieses Tool ist zwar grafisch nicht sehr anspruchsvoll, aber das muss ein Datenbank-Browser meiner Meinung nach auch nicht sein. Man kann mit ihm alle Grundfunktionalitäten abdecken wie zum Beispiel:
- Neue Datenbanken erstellen
- Bestehende Datenbanken einlesen (Daten sowie Struktur anzeigen)
- Strukturen verändern (Tabellen und Indizes erstellen, ändern und löschen)
- SQL-Abfragen ausführen

Dienstag, 14. Juni 2011

Versionierung in .Net - Assembly Version setzen und auslesen

Wie ist eine Versionsnummer aufgebaut?
Eine Versionsnummer sieht z. B. so aus: 1.6.34.55
Diese Werte stehen standardmäßig für folgende Werte: Major Version, Minor Version, Build Number, Revision.

Wie kann man einfach und schnell eine .Net-Applikation mit einer Versionsnummer versehen?

Dieses kann man ganz einfach realisieren indem man die AssemblyInfo.cs anpasst. Die Datei enthält standardmäßig folgende Codezeile:
[assembly: AssemblyVersion("1.0.0.0")] 

Hier könnte man nun manuell eine neue Versionsnummer eintragen wie zum Beispiel folgende:
[assembly: AssemblyVersion("1.1.3.7")]

Da dieses aber aus der Erfahrung heraus in den meisten Fällen regelmäßig vergessen wird, wäre es doch sinnvoll, wenn sich die Versionsnummer automatisch erhöht wird.

Um dieses einfach, schnell und ohne viel Aufwand realisieren zu können, kann man die Zeile wie folgt anpassen.
[assembly: AssemblyVersion("1.0.*")]

Somit werden die letzten beiden Werte (Build Number und Revision) automatisch inkrementell erhöht.

Das Auslesen der aktuellen Versionsnummer ist genauso einfach. Dieses funktioniert mit folgender Zeile Code:
System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()