Einbetten von SQL Server Express in benutzerdefinierte Anwendungen

Veröffentlicht: 28. Feb 2006

Von Robert Walters

In diesem Whitepaper wird erläutert, wie auf Microsoft SQL Server Express basierende Anwendungen mithilfe von Konfigurationsdateien und der ClickOnce-Bereitstellungstechnologie von Microsoft Visual Studio integriert und bereitgestellt werden.

Auf dieser Seite

 Einführung
 Die Datei "Template.ini" und die Befehlszeilenschalter
 Bereitstellung von SQL Server 2005 Express Edition mithilfe eines Wrappers
 ClickOnce (Visual Studio 2005)
 Lizenzierung
 Schlussbemerkung

Einführung

Da die heutigen Computeranwendungen kontinuierlich an Komplexität gewinnen und immer mehr Informationen speichern und verarbeiten müssen, ist ein stabiles und effizientes Datenbankmodul ein wesentlicher Bestandteil für den Erfolg eines jeden Projekts. Microsoft SQL Server 2005 Express Edition (SQL Server Express) ist ein kompaktes und "freies" Datenbankmodul. Es ersetzt Microsoft SQL Server 2000 Desktop Engine (MSDE 2000). SQL Server Express ähnelt der SQL Server 2005 Workgroup Edition, weist jedoch einige Einschränkungen der Speicher-, Datenbank- und Schemafeatures auf. Besuchen Sie auf der Microsoft-Website die SQL Server 2005 Express-Website (in englischer Sprache), um mehr über die Features von SQL Server 2005 Express Edition zu erfahren.

Bisher war die Erstellung einer benutzerdefinierten Anwendung mit eingebetteter MSDE 2000 ein Prozess in drei Phasen:

  1. Erstellen eines MSI-Pakets.

  2. Zusammenführen der MSDE 2000-Verbindungsmodule.

  3. Ausführen von Setup zum Installieren der benutzerdefinierten Anwendung und MSDE 2000.

SQL Server Express verwendet zum Einbetten des SQL Server Express-Datenbankmoduls keine Verbindungsmodule mehr, sondern enthält eine einzelne ausführbare Setupdatei, die mit Ihrer benutzerdefinierten Anwendung gebündelt werden kann. Diese ausführbare Datei akzeptiert Befehlszeilenparameter für eine reibungslose Installation.

Die beste Art, SQL Server Express in Ihre Anwendung einzubetten, ist abhängig davon, wie Sie die Anwendung bereitstellen möchten. Idealerweise sollten Sie immer die neueste Version von SQL Server Express aus dem Web herunterladen. Dadurch stellen Sie sicher, dass Ihre Kunden immer über die neueste Version verfügen. Es ist jedoch praktikabler, SQL Server Express von einer internen Dateifreigabe zu installieren oder auf demselben Medium wie Ihre benutzerdefinierte Anwendung bereitzustellen.

In diesem Whitepaper werden die Konfigurationsdatei und die Befehlszeilenparameter für die ausführbare Setupdatei sqlexpr.exe erläutert. Da sich Verbindungsmodule nicht durchgesetzt haben, ist diese Art der Konfiguration von SQL Server Express die beste Option für SQL Server 2005. Als Hilfestellung zum einfacheren Einbetten von SQL Server Express enthält dieses Whitepaper auch Anweisungen zum Erstellen einer Wrapperklasse, die Entwickler benutzerdefinierter Anwendungen dabei unterstützt, eine SQL Server Express-Lösung bereitzustellen. Außerdem werden in diesem Whitepaper die Vor- und Nachteile des ClickOnce-Features von Microsoft Visual Studio 2005 zum Bereitstellen benutzerdefinierter SQL Server Express-Anwendungen erläutert.

 

Die Datei "Template.ini" und die Befehlszeilenschalter

Es gibt zwei Möglichkeiten, SQL Server Express-Komponenten programmtechnisch zu installieren, zu ändern und zu entfernen. Zum einen können Sie setup.exe aufrufen und über die Befehlszeile eine Reihe von Parametern übergeben. Alternativ können Sie alle Parameter in einer einzigen Datei konfigurieren und diese Datei als Befehlszeilenparameter an setup.exe übergeben. Die Datei heißt template.ini und befindet sich im Stammverzeichnis von SQL Server Express. Hier ist ein Beispiel für das Starten von Setup und das Übergeben der Konfigurationsdatei:

start /wait setup.exe /qb /settings c:\template.ini

Sollten Sie mit der Microsoft Windows-Befehlszeile nicht vertraut sein: start ist eine Anwendung, mit der ein neues Konsolenfenster geöffnet wird. Der Parameter /wait weist die Konsole an, auf das Ende der Programmausführung zu warten, und sich erst anschließend selbst zu schließen. Eine vollständige Liste der Parameter für den Befehl start lässt sich durch die Übergabe von /? als Parameter abrufen. Der nächste Parameter in der Codezeile ist setup.exe. Dies ist der Name der zu startenden Anwendung: In diesem Fall SQL Server Express Setup. Die übrigen Parameter sind Argumente für das Setupprogramm. Das setup.exe-Argument /qb weist Setup an, den unbeaufsichtigten Modus auszuführen, der keine Interaktion des Benutzers erfordert. Dieser Modus bietet dem Benutzer eine visuelle Statusinformation über die Installation.

Alternativ können Sie /qn angeben. Der einzige Unterschied zwischen /qb und /qn ist, dass der Benutzer bei /qn keine visuelle Statusinformation erhält.

Alle Fehler von Setup in SQL Server werden in den Setup-Protokolldateien festgehalten. Wenn Sie sich bei einem Installationsproblem zur Unterstützung an Microsoft Support Services wenden, möchte der Supportmitarbeiter wahrscheinlich, dass Sie diese Dateien bereithalten. In der Standardeinstellung befinden sich diese Dateien unter folgendem Pfad:

C:\Programme\Microsoft SQL Server\90\Setup Bootstrap\LOG\Files

Wenn bei der Entwicklung einer benutzerdefinierten SQL Server Express-Installation Probleme auftreten, sind diese Dateien ein guter Ausgangspunkt für das Debuggen.

Der Befehlszeilenparameter /settings weist Setup an, alle Installationsinformationen aus der Datei abzurufen, die im nächsten Parameter festgelegt wird. In dem Codebeispiel ist die Datei template.ini im Stammverzeichnis von Laufwerk C: gespeichert.

Wichtig   Wenn Sie SQL Server Express heruntergeladen haben, wird die Anwendung setup.exe möglicherweise nicht angezeigt, da wahrscheinlich eine einzelne SQLEXPR.EXE-Datei heruntergeladen wurde. In diesem Fall müssen Sie diese Anwendung über die Befehlszeile aufrufen, um die SQL Server Express-Dateien aus dieser komprimierten ausführbaren Datei zu extrahieren. Führen Sie zum Extrahieren SQLEXPR /X über die Befehlszeile aus. Ein Dialogfeld wird mit der Aufforderung angezeigt, einen Speicherort für die extrahierten Dateien anzugeben. Die SQL Server Express-Dateien werden in das angegebene Verzeichnis kopiert. Diese Dateien enthalten neben anderen Dateien und Ordnern die beiden Dateien setup.exe und template.ini.

Bei der Datei template.ini handelt es sich um eine Nur-Text-Datei, die mithilfe eines Texteditors wie Notepad geöffnet werden kann. Wenn Sie diese Datei öffnen, wird eine lange kommentierte Einführung mit Beispielen zur Verwendung der Datei angezeigt. Die Datei selbst ist umfangreich dokumentiert. Viele Optionen werden ausführlich in der Datei selbst erläutert. Aus diesem Grund sind in diesem Whitepaper nicht alle Optionen aufgeführt. Stattdessen folgen nur ein paar spezielle Parameter.

PIDKEY - Dieser Parameter wird für SQL Server Express-Installationen nicht benötigt. Alle anderen SKUs erfordern diesen Parameter.

ADDLOCAL - Dieser Parameter gibt die zu installierenden Komponenten an. Wenn ADDLOCAL nicht angegeben ist, kann Setup nicht ausgeführt werden. Ein Benutzer kann ADDLOCAL=ALL angeben, um alle Komponenten zu installieren. Für SQL Server Express folgen alle für ADDLOCAL verfügbaren Optionen.

Tabelle 1

Parameter ADDLOCAL

Beschreibung

SQL_Engine

Installiert die SQL Server-Datenbank inklusive der Dienste SQL Server und SQL Browser.

SQL_Data_Files

Installiert die SQL Server-Kerndatenbanken inklusive master, der Ressourcendatenbank und tempdb.

SQL_Replication

Installiert Dateien, die für die Unterstützung der Replikation in SQL Server Express erforderlich sind.

Client_Components

Installiert Komponenten für die Kommunikation zwischen Clients und Servern inklusive Netzwerkbibliotheken für ODBC und OLE DB. Außerdem werden Anwendungen installiert, wie bspw. das Dienstprogramm sqlcmd (Ersatz für oSQL), SQL Server-Konfigurations-Manager und das Tool zur Oberflächenkonfiguration.

Connectivity

Installiert Software Development Kits mit Ressourcen für Modellentwickler und Programmierer. Dazu zählen SQL Server Management Objects (SMO) und Replication Management Objects (RMO).

REMOVE - Dieser Parameter ähnelt ADDLOCAL. Anstatt Komponenten hinzuzufügen, wird eine bestimmte Komponente entfernt bzw. SQL Server Express vollständig deinstalliert, wenn REMOVE=ALL verwendet wird. Im folgenden Beispiel wird die Clientkomponente einer bestehenden SQL Server Express-Installation entfernt.

  REMOVE=Client_Components.  

Ein Instanzname muss nicht angegeben werden, da Client_Components sich nicht auf Instanzen bezieht. Beim Entfernen der Unterstützung für SQL_Replication müssten Sie außerdem Folgendes hinzufügen:

  INSTANCENAME=<<name of the SQL Server Express Instance>>

UPGRADE - Dieser Parameter wird bei der Aktualisierung von MSDE nach SQL Server 2005 Express Edition verwendet. Bei der Verwendung von UPGRADE ist außerdem ein Instanzname anzugeben, der mit der zu aktualisierenden MSDE-Instanz identisch ist, da bis zu 16 MSDE-Instanzen auf einem einzelnen Computer möglich sind. Ein Beispielparameter für UPGRADE ist:

  UPGRADE=SQL_Engine INSTANCENAME=MYMSDE

Beim Schreiben benutzerdefinierter Anwendungen kann es schwierig werden, sich alle Parameternamen für Ihre Projekte zu merken. Zur Vereinfachung können Sie eine benutzerdefinierte Wrapperklasse schreiben, um die Festlegung der Parameter zu kapseln und einen wieder verwendbaren Stub für Ihre Anwendungen bereitzustellen. In der Wrapperklasse sind nicht alle verfügbaren Optionen enthalten, sie sollte jedoch als Vorgabe dienen, um Ihre persönlichen Installationsanforderungen zu erfüllen.

 

Bereitstellung von SQL Server 2005 Express Edition mithilfe eines Wrappers

Als Entwickler benutzerdefinierter Anwendungen haben Sie drei Optionen zur Integration von SQL Server Express in Ihre Anwendung:

  • Installieren Sie zuerst SQL Server Express und dann die benutzerdefinierte Anwendung.

  • Installieren Sie zuerst die benutzerdefinierte Anwendung und dann SQL Server Express.

  • Erstellen Sie einen Wrapper, der den zweiteiligen Prozess der ersten beiden Optionen zusammenfasst.

Hinweis   Ein SQL Server Express-Wrapper kann nicht auf MSI basieren, da Windows Installer keine mehrfache Instanziierung des Windows Installer-Diensts unterstützt.

Der Schwerpunkt im letzten Teil dieses Abschnitts liegt auf der Erstellung eines Wrappers für die benutzerdefinierte Anwendung. Im Beispielcode handelt es sich beim Wrapper um eine einfache Klasse mit drei öffentlichen Methoden: IsExpressInstalled, EnumSQLInstances und InstallExpress. Idealerweise müssen Sie nicht wissen, ob SQL Server Express oder andere Instanzen von SQL Server auf dem lokalen Computer bereits installiert sind. In diesem Beispiel sind sie für den Fall enthalten, dass Sie Endbenutzern die Möglichkeit geben möchten, eine vorhandene Instanz von SQL Server Express auszuwählen, für die Ihre Anwendung installiert werden soll, statt immer neue Instanzen zu erstellen.

Hinweis   Als bewährte Methode sollten die meisten benutzerdefinierten Anwendungen dieselbe SQL Server Express-Instanz verwenden. Dies wird durch das Feature für Benutzerinstanzen von SQL Server Express erreicht. Weitere Informationen zu Benutzerinstanzen erhalten Sie im Whitepaper SQL Server Express Edition User Instances auf MSDN (in englischer Sprache).

Zuerst muss eine einfache Klasse erstellt werden. Diese Klasse enthält lokale Variablen der meisten Befehlszeilenschalter, die von der ausführbaren Installationsdatei SQLEXP.EXE unterstützt werden. Diese Schalter sind als Eigenschaften des Klassenobjekts enthalten.

Wichtig   Der folgende Code ist nur als Richtlinie für die Installation von SQL Server Express mit der benutzerdefinierten Anwendung gedacht. Er ist nicht vollständig und enthält keine strikten Routinen zur Fehlerbehandlung.

   public class EmbeddedInstall
        {
            #region Internal variables

            //Variables for setup.exe command line
            private string instanceName = "SQLEXPRESS";
            private string installSqlDir = "";
            private string installSqlSharedDir = "";
            private string installSqlDataDir = "";
            private string addLocal = "All";
            private bool sqlAutoStart = true;
            private bool sqlBrowserAutoStart = false;
            private string sqlBrowserAccount = "";
            private string sqlBrowserPassword = "";
            private string sqlAccount = "";
            private string sqlPassword = "";
            private bool sqlSecurityMode = false;
            private string saPassword = "";
            private string sqlCollation = "";
            private bool disableNetworkProtocols = true;
            private bool errorReporting = true;
            private string sqlExpressSetupFileLocation =
 System.Environment.GetEnvironmentVariable("TEMP") + "\\sqlexpr.exe";

            #endregion
            #region Properties
            public string InstanceName
            {
                get
                {
                    return instanceName;
                }
                set
                {
                    instanceName = value;
                }
            }

            public string SetupFileLocation
            {
                get
                {
                    return sqlExpressSetupFileLocation;
                }
                set
                {
                    sqlExpressSetupFileLocation = value;
                }
            }

            public string SqlInstallSharedDirectory
            {
                get
                {
                    return installSqlSharedDir;
                }
                set
                {
                    installSqlSharedDir = value;
                }
            }
            public string SqlDataDirectory
            {
                get
                {
                    return installSqlDataDir;
                }
                set
                {
                    installSqlDataDir = value;
                }
            }
            public bool AutostartSQLService
            {
                get
                {
                    return sqlAutoStart;
                }
                set
                {
                    sqlAutoStart = value;
                }
            }
            public bool AutostartSQLBrowserService
            {
                get
                {
                    return sqlBrowserAutoStart;
                }
                set
                {
                    sqlBrowserAutoStart = value;
                }
            }
            public string SqlBrowserAccountName
            {
                get
                {
                    return sqlBrowserAccount;
                }
                set
                {
                    sqlBrowserAccount = value;
                }
            }
            public string SqlBrowserPassword
            {
                get
                {
                    return sqlBrowserPassword;
                }
                set
                {
                    sqlBrowserPassword = value;
                }
            }
            //Defaults to LocalSystem
            public string SqlServiceAccountName
            {
                get
                {
                    return sqlAccount;
                }
                set
                {
                    sqlAccount = value;
                }
            }
            public string SqlServicePassword
            {
                get
                {
                    return sqlPassword;
                }
                set
                {
                    sqlPassword = value;
                }
            }
            public bool UseSQLSecurityMode
            {
                get
                {
                    return sqlSecurityMode;
                }
                set
                {
                    sqlSecurityMode = value;
                }
            }
            public string SysadminPassword
            {
                set
                {
                    saPassword = value;
                }
            }
            public string Collation
            {
                get
                {
                    return sqlCollation;
                }
                set
                {
                    sqlCollation = value;
                }
            }
            public bool DisableNetworkProtocols
            {
                get
                {
                    return disableNetworkProtocols;
                }
                set
                {
                    disableNetworkProtocols = value;
                }
            }
            public bool ReportErrors
            {
                get
                {
                    return errorReporting;
                }
                set
                {
                    errorReporting = value;
                }
            }
            public string SqlInstallDirectory
            {
                get
                {
                    return installSqlDir;
                }
                set
                {
                    installSqlDir = value;
                }
            }

            #endregion

Wenn Sie nun die lokalen Variablen und Eigenschaften für das Klassenobjekt eingerichtet haben, können Sie an den öffentlichen Methoden IsExpressInstalled, EnumSQLInstances und InstallExpress arbeiten.

Im Fall einer lokalen Serverinstallation können Sie einfach die lokale Registrierung daraufhin überprüfen, ob SQL Server Express oder andere Instanzen von SQL Server installiert sind. Die Methode im folgenden Code überprüft den Schlüsselwert "Edition" an der folgenden Stelle:

HKEY_LOCAL_MACHINE\Software\Microsoft\Microsoft SQL Server\MSSQL.X

X steht dabei für eine Instanz von SQL Server.

IsExpressInstalled

           public bool IsExpressInstalled()
            {
                using (RegistryKey Key = 
Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Microsoft SQL 
Server\\", false))
                {
                    if (Key == null) return false;
                    string[] strNames;
                    strNames = Key.GetSubKeyNames();

                    //If we cannot find a SQL Server registry key, we 
don't have SQL Server Express installed
                    if (strNames.Length == 0) return false;

                    foreach (string s in strNames)
                    {
                        if (s.StartsWith("MSSQL."))
                        {
                            //Check to see if the edition is "Express Edition"
                            using (RegistryKey KeyEdition = 
Key.OpenSubKey(s.ToString() + "\\Setup\\", false))
                            {
                                if ((string)KeyEdition.GetValue("Edition") == "Express Edition")
                                {
                                    //If there is at least one instance of 
SQL Server Express installed, return true
                                    return true;
                                }
                            }
                        }
                    }
                }
                return false;
            }

Mit Verwendung der lokalen Registrierung können Sie weitere Informationen über alle SQL Server-Instanzen einholen, unabhängig von der Version, die auf dem lokalen Server installiert ist. Diese Informationen sind hilfreich, wenn Sie eine komfortablere Installation bereitstellen möchten. Die Methode im folgenden Codebeispiel übernimmt einen Verweis und füllt einen Zeichenfolgen-Array für Instanzen, Editionen und Versionen. Sie gibt die Anzahl der Instanzen von SQL Server zurück, die auf dem lokalen Computer installiert sind.

EnumSQLInstances

public int EnumSQLInstances(ref string[] strInstanceArray, ref string[] strEditionArray, ref string[] strVersionArray)
            {
                using (RegistryKey Key = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Microsoft SQL Server\\", false))
                {
                    if (Key == null) return 0;
                    string[] strNames;
                    strNames = Key.GetSubKeyNames();

                    //If we can not find a SQL Server registry key, we return 0 for none
                    if (strNames.Length == 0) return 0;

                    //How many instances do we have?
                    int iNumberOfInstances = 0;

                    foreach (string s in strNames)
                    {
                        if (s.StartsWith("MSSQL."))
                            iNumberOfInstances++;
                    }

                    //Reallocate the string arrays to the new number of instances
                    strInstanceArray = new string[iNumberOfInstances];
                    strVersionArray = new string[iNumberOfInstances];
                    strEditionArray = new string[iNumberOfInstances];
                    int iCounter = 0;

                    foreach (string s in strNames)
                    {
                        if (s.StartsWith("MSSQL."))
                        {
                            //Get Instance name
                            using (RegistryKey KeyInstanceName = 
Key.OpenSubKey(s.ToString(), false))
                            {
                                strInstanceArray[iCounter] = 
(string)KeyInstanceName.GetValue("");
                            }

                            //Get Edition
                            using (RegistryKey KeySetup = 
Key.OpenSubKey(s.ToString() + "\\Setup\\", false))
                            {
                                strEditionArray[iCounter] = 
(string)KeySetup.GetValue("Edition");
                                strVersionArray[iCounter] = 
(string)KeySetup.GetValue("Version");
                            }

                            iCounter++;
                        }
                    }
                    return iCounter;
                }
            }

Nun können Sie SQL Server Express installieren. Wandeln Sie zunächst die Eigenschaften der Klasse in ein Befehlszeilenargument um, das an die Installationsanwendung SQLEXPR.EXE übergeben werden kann. Von der folgenden Methode wird diese Aufgabe ausgeführt.

           private string BuildCommandLine()
            {
                StringBuilder strCommandLine = new StringBuilder();

                if (!string.IsNullOrEmpty(installSqlDir))
                {
                    strCommandLine.Append(" 
INSTALLSQLDIR=\"").Append(installSqlDir).Append("\"");
                }

                if (!string.IsNullOrEmpty(installSqlSharedDir))
                {
                    strCommandLine.Append(" 
INSTALLSQLSHAREDDIR=\"").Append(installSqlSharedDir).Append("\"");
                }

                if (!string.IsNullOrEmpty(installSqlDataDir))
                {
                    strCommandLine.Append(" 
INSTALLSQLDATADIR=\"").Append(installSqlDataDir).Append("\"");
                }

                if (!string.IsNullOrEmpty(addLocal))
                {
                    strCommandLine.Append(" ADDLOCAL=\"").Append(addLocal).Append("\"");
                }

                if (sqlAutoStart)
                {
                    strCommandLine.Append(" SQLAUTOSTART=1");
                }
                else
                {
                    strCommandLine.Append(" SQLAUTOSTART=0");
                }

                if (sqlBrowserAutoStart)
                {
                    strCommandLine.Append(" SQLBROWSERAUTOSTART=1");
                }
                else
                {
                    strCommandLine.Append(" SQLBROWSERAUTOSTART=0");
                }

                if (!string.IsNullOrEmpty(sqlBrowserAccount))
                {
                    strCommandLine.Append(" 
SQLBROWSERACCOUNT=\"").Append(sqlBrowserAccount).Append("\"");
                }

                if (!string.IsNullOrEmpty(sqlBrowserPassword))
                {
                    strCommandLine.Append(" 
SQLBROWSERPASSWORD=\"").Append(sqlBrowserPassword).Append("\"");
                }

                if (!string.IsNullOrEmpty(sqlAccount))
                {
                    strCommandLine.Append(" SQLACCOUNT=\"").Append(sqlAccount).Append("\"");
                }

                if (!string.IsNullOrEmpty(sqlPassword))
                {
                    strCommandLine.Append(" SQLPASSWORD=\"").Append(sqlPassword).Append("\"");
                }

                if (sqlSecurityMode == true)
                {
                    strCommandLine.Append(" SECURITYMODE=SQL");
                }

                if (!string.IsNullOrEmpty(saPassword))
                {
                    strCommandLine.Append(" SAPWD=\"").Append(saPassword).Append("\"");
                }

                if (!string.IsNullOrEmpty(sqlCollation))
                {
                    strCommandLine.Append(" SQLCOLLATION=\"").Append(sqlCollation).Append("\"");
                }

                if (disableNetworkProtocols == true)
                {
                    strCommandLine.Append(" DISABLENETWORKPROTOCOLS=1");
                }
                else
                {
                    strCommandLine.Append(" DISABLENETWORKPROTOCOLS=0");
                }

                if (errorReporting == true)
                {
                    strCommandLine.Append(" ERRORREPORTING=1");
                }
                else
                {
                    strCommandLine.Append(" ERRORREPORTING=0");
                }

                return strCommandLine.ToString();
            }

Nun können Sie die Methode InstallExpress erstellen.

InstallExpress

       public bool InstallExpress()
            {
                              
                //In both cases, we run Setup because we have the file.
                Process myProcess = new Process();
                myProcess.StartInfo.FileName = sqlExpressSetupFileLocation;
                myProcess.StartInfo.Arguments = "/qb " + BuildCommandLine();
                /*      /qn -- Specifies that setup run with no user interface.
                        /qb -- Specifies that setup show only the basic 
user interface. Only dialog boxes displaying progress information are 
displayed. Other dialog boxes, such as the dialog box that asks users if 
they want to restart at the end of the setup process, are not displayed.
                */
                myProcess.StartInfo.UseShellExecute = false;

                return myProcess.Start();
                
            }

Erstellen Sie nun die Beispielanwendung, die diese Wrapperklasse aufruft.

class Program
    {
        static void Main(string[] args)
        {
            EmbeddedInstall EI = new EmbeddedInstall();

            if (args.Length > 0)
            {
                int i = 0;
                while (i < args.Length)
                {
                    if ((string)args[i].ToUpper() == "-V")
                    {
                        string[] strInstanceArray = new string[0];
                        string[] strVersionArray = new string[0];
                        string[] strEditionArray = new string[0];

                        int iInstances = EI.EnumSQLInstances(ref 
strInstanceArray, ref strEditionArray, ref strVersionArray);
                        if (iInstances > 0)
                        {
                            for (int j = 0; j <= iInstances - 1; j++)
                            {
                                Console.WriteLine("SQL Server Instance: 
\"" + strInstanceArray[j].ToString() + "\" -- " + 
strEditionArray[j].ToString() + "   (" + strVersionArray[j].ToString() + 
")");
                            }

                        }
                        else
                        {
                            Console.WriteLine("No instance of SQL Server 
Express found on local server.\n\n");
                        }

                        return;
                    }

                    if ((string)args[i].ToUpper() == "-I")
                    {
                        if (EI.IsExpressInstalled())
                        {
                            Console.WriteLine("An instance of SQL Server 
Express is installed.\n\n");
                        }
                        else
                        {
                            Console.WriteLine("There are no SQL Server 
Express instances installed.\n\n");
                        }

                        return;
                    }

                    i++;
                }
            }

            Console.WriteLine("\nInstalling SQL Server 2005 Express Edition\n");

            EI.AutostartSQLBrowserService = false;
            EI.AutostartSQLService = true;
            EI.Collation = "SQL_Latin1_General_Cp1_CS_AS";
            EI.DisableNetworkProtocols = false;
            EI.InstanceName = "SQLEXPRESS";
            EI.ReportErrors = true;
            EI.SetupFileLocation = "C:\\Downloads\\sqlexpr.exe";  
//Provide location for the Express setup file
            EI.SqlBrowserAccountName = ""; //Blank means LocalSystem
            EI.SqlBrowserPassword = ""; // N/A
            EI.SqlDataDirectory = "C:\\Program Files\\Microsoft SQL Server\\";
            EI.SqlInstallDirectory = "C:\\Program Files\\";
            EI.SqlInstallSharedDirectory = "C:\\Program Files\\";
            EI.SqlServiceAccountName = ""; //Blank means Localsystem
            EI.SqlServicePassword = ""; // N/A
            EI.SysadminPassword = "ThIsIsALoNgPaSsWoRd1234!!"; //<<Supply 
a secure sysadmin password>>
            EI.UseSQLSecurityMode = true;

            EI.InstallExpress();

            Console.WriteLine("\nInstalling custom application\n");


            //If you need to run another MSI install, remove the following comment lines 
            //and fill in information about your MSI

            /*Process myProcess = new Process();
            myProcess.StartInfo.FileName = "";//<<Insert the path to your MSI file here>>
            myProcess.StartInfo.Arguments = ""; //<<Insert any command line parameters here>>
            myProcess.StartInfo.UseShellExecute = false;
            myProcess.Start();*/

        }

 

ClickOnce (Visual Studio 2005)

ClickOnce ist ein neues Feature, das im Microsoft .NET Framework 2.0 enthalten ist. Mit ClickOnce können Sie Windows-Clientanwendungen auf einem Computer bereitstellen, indem Sie die Anwendungsdateien auf einem Web- oder Dateiserver speichern, auf den der Client zugreifen kann, und dem Benutzer anschließend einen Link bereitstellen. Der Benutzer kann dadurch Anwendungen von zentral verwalteten Servern herunterladen und ausführen, ohne dass Administrator-Privilegien auf dem Clientcomputer notwendig sind.

In diesem Abschnitt wird der ClickOnce/SQL Server Express-Vorgang mit der Entwicklung einer einfachen WinForm-Anwendung verdeutlicht. Diese Anwendung verwendet die Beispieldatenbank AdventureWorks, die im Microsoft Download Center unter "SQL Server 2005 Express Edition Documentation and Samples" heruntergeladen werden kann (in englischer Sprache).

Dieses Beispiel verdeutlicht, wie Sie eine einzelne WinForm-Anwendung erstellen, mit der die Abteilungen in der Tabelle HumanResources.Department der Datenbank AdventureWorks angezeigt werden können.

So erstellen Sie eine WinForm-Anwendung, mit der die Tabelle "Department" angezeigt wird:

  1. Starten Sie Visual Studio.

  2. Erstellen Sie ein neues Windows-Anwendungsprojekt.

  3. Wenn der Designer für "Form1" geöffnet wird, fügen Sie einen Verweis zur Datenbank AdventureWorks hinzu.

  4. Klicken Sie mit der rechten Maustaste im Bereich Projektmappen-Explorer auf den Knoten Projekt und wählen Sie dann Hinzufügen und Vorhandenes Element aus. Navigieren Sie zur AdventureWorks-Datenbank und klicken Sie auf OK.

    Der Assistent zum Konfigurieren von Datenquellen wird geöffnet.

  5. Wählen Sie unter dem Knoten Tabelle die Tabelle Department aus und fahren Sie mit dem Assistenten fort.

    Wenn der Assistent abgeschlossen ist, werden das Datenbanksymbol "AdventureWorks.MDF" im Bereich Projektmappen-Explorer und eine neue "AdventureWorks"-Verbindung im Datenbank-Explorer angezeigt. Mit dem Datenbank-Explorer können Sie Datenbankvorgänge ausführen, wie das Erstellen neuer Tabellen, das Abfragen und Ändern vorhandener Daten und andere Funktionen zur Datenbankentwicklung.

  6. Fügen Sie der WinForm-Anwendung das Steuerelement DataGridView hinzu. Dieses Steuerelement befindet sich in der Toolbox. Wenn Sie das DataGridView-Steuerelement auf die Entwurfsoberfläche ziehen, haben Sie die Option zur Auswahl des AdventureWorks-DataSets, das Sie im Assistenten zum Konfigurieren von Datenquellen erstellt haben. Dieses Dialogfeld wird in Abbildung 1 dargestellt.

    Dialogfeld zur DataGridView-Konfiguration
    Abbildung 1: Dialogfeld zur DataGridView-Konfiguration

    Nach der Konfiguration einer Datenquelle sollte die Anwendung ausgeführt werden können, und das Grid-Steuerelement sollte die Werte für die Tabelle Department anzeigen (siehe Abbildung 2)

    Beispielanwendung "AdventureWorks"
    Abbildung 2: Beispielanwendung "AdventureWorks"

Diese Anwendung können Sie nun mithilfe von ClickOnce bereitstellen.

So stellen Sie die Anwendung mithilfe von ClickOnce bereit

  1. Zum Veröffentlichen der Anwendung wählen Sie im Menü Erstellen die Option Veröffentlichen aus. Der Webpublishing-Assistent wird geöffnet, wie in Abbildung 3 dargestellt.

    Webpublishing-Assistent: Wo möchten Sie die Anwendung veröffentlichen?
    Abbildung 3: Webpublishing-Assistent: Wo möchten Sie die Anwendung veröffentlichen?

    Auf der ersten Seite des Assistenten wird festgelegt, wo die kompilierten Bits physikalisch gespeichert werden sollen. In diesem Beispiel, wie in Abbildung 3 dargestellt, wird die Anwendung auf der lokalen Festplatte veröffentlicht.

  2. Geben Sie im Feld Veröffentlichungsort für diese Anwendung angeben die Zeichenfolge C:\deploy\ViewDepartments ein.

  3. Klicken Sie auf Weiter, um die nächste Seite des Webpublishing-Assistenten anzuzeigen, wie in Abbildung 4 dargestellt. Auf dieser Seite wird der Speicherort festgelegt, von dem die Benutzer die Anwendung installieren.

    Webpublishing-Assistent: Wie werden Benutzer die Anwendung installieren?
    Abbildung 4: Webpublishing-Assistent: Wie werden Benutzer die Anwendung installieren?

  4. Wählen Sie für dieses Beispiel Von CD-ROM oder DVD-ROM.

  5. Klicken Sie auf Weiter, um die nächste Seite des Webpublishing-Assistenten anzuzeigen, wie in Abbildung 5 dargestellt. Auf dieser Seite wird festgelegt, ob die Anwendung nach Updates suchen soll.

    Webpublishing-Assistent: Auf Updates überprüfen
    Abbildung 5: Webpublishing-Assistent: Auf Updates überprüfen

  6. ClickOnce stattet Anwendungen mit der Fähigkeit aus, zu bestimmten Zeiten nach Updates zu suchen, bspw. beim Starten der Anwendung oder beim Aufrufen der entsprechenden Update-APIs durch den Anwendungsentwickler. Beim Verwenden dieses Features mit einer Datenbank treten ein paar Probleme auf. Diese werden weiter unten in diesem Dokument erläutert. Wählen Sie für dieses Beispiel Anwendung sucht nicht nach Updates.

  7. Klicken Sie auf Weiter, um die letzte Seite des Assistenten anzuzeigen, wie in Abbildung 6 dargestellt.

    Webpublishing-Assistent: Veröffentlichen
    Abbildung 6: Webpublishing-Assistent: Veröffentlichen

    Neben der Zusammenfassung zeigt der Assistent auch eine Benachrichtigung an, dass Setup unter Software eine Verknüpfung und einen Eintrag für Ihre Anwendung installiert, da Sie auf eine CD oder DVD schreiben.

  8. Klicken Sie auf Fertig stellen.

Sie können eine Anwendung schreiben, die sich nur auf dem Anwendungsserver befindet und nicht auf dem Clientcomputer installiert wird. Trotzdem fordert ClickOnce den Benutzer auf, alle fehlenden erforderlichen Komponenten wie .NET Framework 2.0 oder SQL Server Express zu installieren, wie in Abbildung 7 dargestellt.

Nicht installierte erforderliche Komponenten beim Starten der Anwendung
Abbildung 7: Nicht installierte erforderliche Komponenten beim Starten der Anwendung

Hinweis   Unabhängig davon, ob die Anwendung dafür entworfen wurde, auf einem Anwendungsserver ausgeführt oder lokal installiert zu werden, wird SQL Server Express immer auf dem lokalen Computer installiert, wenn die benutzerdefinierte Anwendung dies erfordert.

Wenn der Webpublishing-Assistent abgeschlossen ist, befinden sich im Bereitstellungsverzeichnis neue Dateien. Unter diesen Dateien befinden sich die komprimierten Datendateien und die Setup-Installationsanwendung. Diese Dateien können Sie auf CD kopieren und an die Benutzer verteilen, um ihnen die notwendigen Informationen über Anwendungen, die SQL Server Express verwenden, bereitzustellen.

Wichtig   Ein Benutzer ohne Administratorberechtigungen auf dem lokalen Computer kann das .NET Framework oder SQL Server Express nicht installieren. In diesem Fall sollten Systemadministratoren diese Komponenten bereitstellen. Systemadministratoren können dies entweder manuell durchführen oder mithilfe eines Verwaltungssystems für verteilte Software, bspw. Microsoft Systems Management Server.

Aktualisierung von ClickOnce-Bereitstellungen, die SQL Server Express verwenden

In diesem Szenario wird angenommen, dass der Endbenutzer Ihre Anwendung erfolgreich installiert hat. Der Benutzer hat alle erforderlichen Komponenten installiert, und die Anwendung wird erfolgreich ausgeführt.

In der Beispielanwendung wurden Daten in die Datenbank der Version 1.0 eingegeben. Die Entwickler der benutzerdefinierten Anwendungen haben nun eine neue Version (2.0) der Anwendung veröffentlicht. Diese neue Version verfügt in der Tabelle Departments über eine zusätzliche Spalte mit dem Namen Location. Diese neue Spalte enthält den geografischen Standort der Abteilung. Wenn der Entwickler Version 2.0 bereitstellt, wird die neue Version der Datenbank auf den Client übertragen, und die vorherige Version wird automatisch in einen separaten Ordner mit dem Namen Pre verschoben. Der Entwickler muss nun ein Skript zur Migration der Datenbank schreiben, um alle Daten von Version 1.0 im Ordner Pre in die neue Datenbank zu verschieben. Da Visual Studio keine Tools zur Unterstützung dieser Migration enthält, bleibt dies dem Entwickler selbst überlassen. Andernfalls werden die Daten, die in Version 1.0 eingegeben wurden, nicht in der Anwendung verfügbar sein. Wenn der Entwickler eine Zwischenversion (bspw. 2.1) veröffentlicht, um dieses Migrationsproblem zu beheben, oder wenn der Entwickler einfach durch die Anzeige der Struktur im Server-Explorer auf die MDF-Datei zugreift, erkennt ClickOnce, dass die Datums- und Zeitangabe geändert wurde, und stellt Version 2.1 der Datenbank bereit. Dadurch wird Version 2.0 der Datenbank in den Ordner Pre verschoben, und Version 1.0 der Datenbank wird gelöscht. Die Ergebnisse sind vollständiger Datenverlust und unzureichende Zufriedenheit der Kunden.

Um dies zu vermeiden, sollten die Datenbankdateien nicht in Visual Studio enthalten sein, wenn die Anwendung bereitgestellt wird. Stellen Sie stattdessen Installationskripts zum Erstellen der Datenbank bereit. Wenn Sie ein ClickOnce-Update durchführen, müssen Sie außerdem ein separates Aktualisierungsskript schreiben und aufrufen. Das Beispiel ViewDepartments aus dem vorherigen Abschnitt wird im Folgenden verwendet, um die Behelfslösung zu veranschaulichen.

ViewDepartments ist eine einzelne WinForm-Anwendung, die eine Verbindung zur Datenbank AdventureWorks herstellt und die Tabelle Departments anzeigt. Bei der Bereitstellung dieser Anwendung haben Sie Visual Studio zur MDF-Datei von AdventureWorks verwiesen, wodurch eine neue Datenquelle erstellt wurde. Wenn die Anwendung nun funktioniert und ClickOnce zur Bereitstellung verwendet wurde, enthält die Anwendung immer die MDF-Datei von AdventureWorks und verursacht die zuvor erwähnten Überschreibungsprobleme.

So vermeiden Sie unerwünschten Datenverlust in Ihrer Anwendung

  1. Kopieren Sie die MDF-Datei nicht in das Ausgabeverzeichnis.

    Klicken Sie im Bereich Projektmappen-Explorer auf das Datenbanksymbol AdventureWorks, wie in Abbildung 8 dargestellt. Wählen Sie im Bereich Eigenschaften für die Eigenschaft In Ausgabeverzeichnis kopieren die Option Nicht kopieren aus.

    Eigenschaft "In Ausgabeverzeichnis kopieren"
    Abbildung 8: Eigenschaft "In Ausgabeverzeichnis kopieren"

  2. Veröffentlichen Sie nicht die AdventureWorks-Datenbankdateien.

    Öffnen Sie den Bereich Projekteigenschaften, indem Sie im Menü Projekt die Option Eigenschaften auswählen. Klicken Sie auf der Registerkarte Veröffentlichen auf Anwendungsdateien. Ein Dialogfeld wird geöffnet, das eine Liste aller Dateien der Projektmappe enthält. Ändern Sie den Veröffentlichungsstatus für die MDF- und LDF-Datei der Datenbank AdventureWorks auf Ausschließen, wie in Abbildung 9 dargestellt

    Ausschließen von Datenbankdateien
    Abbildung 9: Ausschließen von Datenbankdateien

  3. Erstellen Sie ein Skript zur Erstellung der Datenbank AdventureWorks.

    Ein Skript für eine Datenbank kann auf viele Arten erstellt werden. In SQL Server Management Studio klicken Sie mit der rechten Maustaste im Objekt-Explorer auf die Datenbank. Dort können Sie das vollständige Skript erstellen. Sie können auch den Assistenten zum Generieren von SQL Server-Skripts verwenden, um weitere Skriptoptionen zu erhalten. Wenn Sie über keine Lizenz für dieses oder ein anderes Skripterstellungstool verfügen, können Sie einfach ein kleines Programm erstellen, in dem das Objektmodell von SQL Server Management Objects (SMO) verwendet wird, um ein Skript mithilfe der Klasse Scripter zu erstellen.

    Hinweis   Wenn Sie SQL Server Express installiert haben und sich für die Installation der Entwicklerkomponenten entschieden haben, befinden sich die SMO-DLLs in der Standardeinstellung unter C:\Programme\Microsoft SQL Server\90\SDK\Assemblies.

Es folgt ein geändertes AdventureWorks-Erstellungsskript, mit dem die Tabelle Departments erstellt und gefüllt wird.

USE [master]
GO
CREATE DATABASE [AdventureWorks] ON  PRIMARY 
( NAME = N'AdventureWorks_Data', FILENAME = N'C:\Program Files\Microsoft
 SQL Server\MSSQL.1\MSSQL\Data\AdventureWorks_Data.mdf' , SIZE = 167936KB 
, MAXSIZE = UNLIMITED, FILEGROWTH = 16384KB )
 LOG ON 
( NAME = N'AdventureWorks_Log', FILENAME = N'C:\Program Files\Microsoft 
SQL Server\MSSQL.1\MSSQL\Data\AdventureWorks_Log.ldf' , SIZE = 2048KB , 
MAXSIZE = 2048GB , FILEGROWTH = 16384KB )
 COLLATE SQL_Latin1_General_CP1_CI_AS
GO
EXEC dbo.sp_dbcmptlevel @dbname=N'AdventureWorks', @new_cmptlevel=90
GO
USE [AdventureWorks]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TYPE [dbo].[Name] FROM [nvarchar](50) NULL
GO
EXEC sys.sp_executesql N'CREATE SCHEMA [HumanResources] AUTHORIZATION [dbo]'
GO
CREATE TABLE [HumanResources].[Department](
   [DepartmentID] [smallint] IDENTITY(1,1) NOT NULL,
   [Name] [dbo].[Name] NOT NULL,
   [GroupName] [dbo].[Name] NOT NULL,
   [ModifiedDate] [datetime] NOT NULL CONSTRAINT 
[DF_Department_ModifiedDate]  DEFAULT (getdate()),
 CONSTRAINT [PK_Department_DepartmentID] PRIMARY KEY CLUSTERED 
(
   [DepartmentID] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Engineering','Research and Development')
GO
insert into [HumanResources].[Department](Name,Groupname) values('Tool 
Design','Research and Development')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Sales','Sales and Marketing')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Marketing','Sales and Marketing')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Purchasing','Inventory Management')
GO
insert into [HumanResources].[Department](Name,Groupname) values('Research 
and Development','Research and Development')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Production','Manufacturing')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Production Control','Manufacturing')
GO
insert into [HumanResources].[Department](Name,Groupname) values('Human 
Resources','Executive General and Administration')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Finance','Executive General and Administration')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Information Services','Executive General and Administration')
GO
insert into [HumanResources].[Department](Name,Groupname) values('Document
 Control','Quality Assurance')
GO
insert into [HumanResources].[Department](Name,Groupname) values('Quality 
Assurance','Quality Assurance')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Facilities and Maintenance','Executive General and 
Administration')
GO
insert into [HumanResources].[Department](Name,Groupname) values('Shipping 
and Receiving','Inventory Management')
GO
insert into [HumanResources].[Department](Name,Groupname) 
values('Executive','Executive General and Administration')
GO
--This next table is used to identify the version of the database
CREATE TABLE AdventureWorks..AppInfo
(Property nvarchar(255) NOT NULL,
Value nvarchar(255))
GO
INSERT INTO AdventureWorks..AppInfo Values('Version','1.0.0.0')
GO

Da die eigentliche MDF-Datei nicht in dieser Projektmappe enthalten ist, müssen Sie die Versionen der Datenbank, mit der die Anwendung verbunden ist, definieren und synchronisieren. Eine einfache Lösung ist es, der AdventureWorks-Datenbank die Tabelle AppInfo hinzuzufügen. Wenn Sie die Anwendung starten, wird zunächst überprüft, ob die Versionen übereinstimmen. Ist dies nicht der Fall, führt die Anwendung entweder ein Aktualisierungsskript aus oder schlägt fehl. In Schritt 3 wird dies näher erläutert.

So implementieren Sie eine Überprüfung der Version

  1. Speichern Sie das Skript als eingebettete Ressource in der Anwendung.

    Vor dem Hinzufügen eines Skripts müssen Sie dem Projekt eine Ressourcendatei hinzufügen. Klicken Sie dazu mit der rechten Maustaste im Bereich Projektmappen-Explorer auf das Projekt, wählen Sie Hinzufügen und anschließend Neues Element aus. Wählen Sie Ressourcendatei aus und klicken Sie auf Hinzufügen. Das Fenster für Ressourcendateidokumente wird geöffnet, wie in Abbildung 10 dargestellt.

    Sie können die SQL-Skripts nun entweder als separate Zeichenfolgen oder als Textdateien hinzufügen. Speichern Sie die Skripts zum Erstellen und Aktualisieren zur Vereinfachung als separate Dateien innerhalb dieser Ressource. Klicken Sie dazu im Dropdown-Menü Ressource hinzufügen auf Vorhandene Datei hinzufügen. Navigieren Sie zu dem im zweiten Schritt erstellten Erstellungsskript und fügen Sie diese Datei hinzu.

    Fenster für Ressourcendateidokumente mit dem Skript zur Datenbankerstellung
    Abbildung 10: Fenster für Ressourcendateidokumente mit dem Skript zur Datenbankerstellung

  2. Ersellen Sie ein Upgrade-Skript für die AdventureWorks-Datenbank.

    Auch wenn Sie Ihre Anwendung nicht unmittelbar aktualisieren müssen, sollten Sie auch das Aktualisierungsskript zum Aktualisieren der Datenbank auf Version 1.0.0.3 einbeziehen.

    USE [AdventureWorks]
    GO
    ALTER TABLE [HumanResources].[Department]
    ADD Location char(2)  
    GO
    UPDATE AdventureWorks..AppInfo set Value='1.0.0.3' where 
    Property='Version'
    GO
    

    Speichern Sie dieses Skript als UpgradeAdventureWorks.sql. Fügen Sie es der Ressourcendatei wie in Schritt 3 beschrieben zu.

  3. Konfigurieren Sie die Anwendung so, dass Versionen überprüft werden, und führen Sie alle notwendigen Skripts aus.

    Sie sollten nun Ihren aktuellen Entwurf ändern, um die Vorgänge zur Versionsüberprüfung und Skriptausführung zu starten.

    Hinweis   Im vorherigen Beispiel enthält die Methode Form_Load Code, der beim Zuweisen des AdventureWorks-Datensatzes über die Benutzeroberfläche automatisch generiert wurde:

    this.departmentTableAdapter.Fill(this.adventureWorks_DataDataSet.Department);
    

    Dieser sollte entfernt oder auskommentiert werden, da zunächst die Datenbankversion überprüft werden soll. Außerdem sollten Sie den Wert der Eigenschaft DataSource (die im Grid-Steuerelement, das Sie in der Benutzeroberfläche an die Datenquelle gebunden haben, bereits gefüllt war) auf None setzen (siehe Abbildung 11).

    Die von Visual Studio automatisch generierte Eigenschaft "DataSource"
    Abbildung 11: Die von Visual Studio automatisch generierte Eigenschaft "DataSource"

Es folgt der vollständige Code der Klasse Form1:

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Text.RegularExpressions;


namespace ViewDepartments
{

    public partial class Form1 : Form
    {

        enum VersionCheck { Failed = 0, Equal, DatabaseIsMoreNew,
 DatabaseIsOlder, DatabaseNotFound };
 
        private SqlConnection sqlCon = new SqlConnection();
        private SqlCommand sqlCmd = new SqlCommand();

        public Form1()
        {
            InitializeComponent();

            if (SetupDatabase() == false)
            {
                return;
            }

            PopulateGrid();
        }

        public bool SetupDatabase()
        {
            bool bContinue = false;

            //Create a connection to SQL Server
            try
            {
                sqlCon.ConnectionString = "Server=.\\sqlexpress;Integrated Security=true";
                sqlCon.Open();
            }
            catch (SqlException sql_ex)
            {
                MessageBox.Show("Fail to connect to SQL Server Express\n" 
+ sql_ex.Number.ToString() + " " + sql_ex.Message.ToString());
                return bContinue;
            }

            //Now that you are connected to Express, check the database 
versions

            switch (CheckVersion())
            {
                case (int)VersionCheck.Equal:
                    {
                        bContinue = true;
                        break;
                    }
                case (int)VersionCheck.Failed:
                    {
                        bContinue = false;
                        break;
                    }
                case (int)VersionCheck.DatabaseIsOlder:
                    {
                        //Run the upgrade script
                        bContinue = 
RunScript(Resource1.UpdateAdventureWorks.ToString());
                        break;
                    }
                case (int)VersionCheck.DatabaseIsMoreNew:
                    {
                        bContinue = false;
                        break;
                    }
                case (int)VersionCheck.DatabaseNotFound:
                    {
                        //Run the creation script
                        bContinue = 
RunScript(Resource1.CreateAdventureWorks.ToString());
                        break;
                    }
                default:
                    {
                        bContinue = false;
                        break; 
                    }

            }

          
            return bContinue;

                    
        }
        public bool RunScript(string strFile)
        {
            string[] strCommands;
            strCommands = ParseScriptToCommands(strFile);
            try
            {
                if (sqlCon.State != ConnectionState.Open) sqlCon.Open();
                
                sqlCmd.Connection = sqlCon;

                foreach (string strCmd in strCommands)
                {
                    if (strCmd.Length > 0)
                    {
                        sqlCmd.CommandText = strCmd;
                        sqlCmd.ExecuteNonQuery();
                    }
                }
            }
            catch (SqlException sql_ex)
            {
                MessageBox.Show(sql_ex.Number.ToString() + " " + 
sql_ex.Message.ToString());
                return false;
            }

            return true;
        }
        public int CheckVersion()
        {
            //Get Version information from application
            Version v=new Version(Application.ProductVersion.ToString());

            try
            {

                string strResult;

                //Verify that the AdventureWorks Database exists
                sqlCmd = new SqlCommand("select count(*) from 
master..sysdatabases where name='AdventureWorks'",sqlCon);
                strResult = sqlCmd.ExecuteScalar().ToString();
                if (strResult == "0")
                {
                    sqlCon.Close();
                    return (int)VersionCheck.DatabaseNotFound;
                }

                sqlCmd = new SqlCommand("SELECT value from 
AdventureWorks..AppInfo where property='version'", sqlCon);
                strResult=(string)sqlCmd.ExecuteScalar();

                Version vDb = new Version(strResult);

                sqlCon.Close();

                if (vDb == v)
                    return (int)VersionCheck.Equal;

                if (vDb > v)
                    return (int)VersionCheck.DatabaseIsMoreNew;

                if (vDb < v)
                    return (int)VersionCheck.DatabaseIsOlder;

            }
            catch (SqlException sql_ex)
            {
                MessageBox.Show(sql_ex.Number.ToString() + " " + 
sql_ex.Message.ToString());
                return (int)VersionCheck.Failed;
            }
            catch (Exception system_ex)
            {
                MessageBox.Show(system_ex.Message.ToString());
                return (int)VersionCheck.Failed;
            }

            return (int)VersionCheck.Failed;
                
        }

        public string[] ParseScriptToCommands(string strScript)
        {
            string[] commands;
            commands = Regex.Split(strScript, "GO\r\n", RegexOptions.IgnoreCase);
            return commands;
        }

        public void PopulateGrid()
        {

            String strCmd = "Select * from [AdventureWorks].[HumanResources].[Department]";
            SqlDataAdapter da;
            
            da = new SqlDataAdapter(strCmd, sqlCon);
            DataSet ds = new DataSet();
            da.Fill(ds, "Departments");
            dataGridView1.DataSource = ds;
            dataGridView1.DataMember = "Departments";
            
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            // TODO: This line of code loads data into the 
'adventureWorks_DataDataSet.Department' table. You can move or remove this 
line as necessary.
            //this.departmentTableAdapter.Fill(this.adventureWorks_DataDataSet.
Department);
        }
    }
}

Im vorherigen Code wurde SetDatabase() aufgerufen. Diese Funktion versucht zunächst, eine Verbindung zu SQL Server Express herzustellen. Ist dieser Aufruf erfolgreich, wird die Methode CheckVersion() aufgerufen. Diese Methode überprüft, ob die Datenbank AdventureWorks existiert. Ist dies der Fall, ruft die Methode CheckVersion() die Versionsnummer aus der Tabelle AppInfo ab. Wenn die Datenbank AdventureWorks nicht existiert, wird das Erstellungsskript ausgeführt, das sich in der Ressourcendatei befindet. Wenn die Version der Datenbank älter ist als die Anwendungsversion, wird das Aktualisierungsskript ausgeführt.

Hinweis   Die Version, die mit der Datenbank verglichen wird, kommt aus der Eigenschaft Dateiversion des Projekts. Diese Eigenschaft kann im Dialogfeld Assemblyinformationen festgelegt werden. Dieses Dialogfeld lässt sich auf der Registerkarte Anwendung in den Projekteigenschaften aufrufen.

Wenn Sie diese Anwendung zum ersten Mal mit einer leeren SQL Server Express-Datenbank ausführen, wird die Datenbank AdventureWorks erstellt, und die vier Spalten der Tabelle Departments werden angezeigt. Bei der nächsten Ausführung der Anwendung wird diese aktualisiert, so dass in der Tabelle eine weitere Spalte mit dem Namen Location enthalten ist.

 

Lizenzierung

Bei Einhaltung bestimmter Richtlinien können Sie SQL Server Express mit Ihrer benutzerdefinierten Anwendung frei verteilen. Zuerst müssen Sie sich auf der SQL Server Express-Website (in englischer Sprache) registrieren, auf der auch die vollständige Anleitung zur Lizenzierung von SQL Server Express zu finden ist. Lesen und bestätigen Sie anschließend den Endbenutzer-Lizenzvertrag.

 

Schlussbemerkung

Weitere Informationen:

Microsoft SQL Server Express-Website (in englischer Sprache)