2010-12-03 20 views
1

Ich muss ein SQL-Skript ausführen, das in einer Datei aus meiner C# -Anwendung ist. Das Problem ist, dass es Objekte erstellt und Befehle auf verschiedenen Datenbanken ausführt.C# SQL Server-Skript ändern Datenbankproblem

Im Skript jedes Mal, ich brauche die aktuelle Datenbank ändern sie den Befehl verwendet

USE [databasename]

und da gibt es viele Objekterstellungen sind verwendet es den Befehl GO eine Menge Zeit, so dass ich gelesen die Datei, bis ich einen GO-Befehl finde und den Satz in der Datenbank laufen lasse; So weit, so gut, aber nachdem der Befehl ausgeführt wurde, kehrt die Verbindung zur Standarddatenbank (in diesem Fall Master) zurück, wobei der letzte USE-Satz ignoriert wird.

Dies ist der Code, den ich verwende, um die Datei zu lesen und das Skript auszuführen.

using (StreamReader reader = new StreamReader(databaseScriptFile)) 
    { 
     DatabaseFactory.CreateDatabase() 
     Database db = new SqlDatabase(connectionstring); 
     txbuilder = new StringBuilder(); 
     bool lastExecute = true;    
     while (!reader.EndOfStream) 
     { 
      text = reader.ReadLine(); 
      if (text.Trim().ToUpper() != "GO") 
      { 
       lastExecute = false; 
       txbuilder.AppendLine(text); 
      } 
      else 
      { 
       lastExecute = true; 
       db.ExecuteNonQuery(CommandType.Text, txbuilder.ToString()); 
       txbuilder.Length = 0; 
      } 
     } 
     //Make sure that the last sentence is executed 
     if (!lastExecute) 
      db.ExecuteNonQuery(CommandType.Text, txbuilder.ToString()); 
    } 

Es scheint, dass es die Verbindung nach jeder ExecuteNonQuery Befehl ausführen sp_reset_conection löscht (das ist, was ich im Profiler erhalten)

Gibt es eine elegante und einfache Möglichkeit, dies zu erledige?

Dank

+0

Was hat das mit 'Enterprise-Library' zu tun? –

+0

Ich verwende das Datenbankobjekt der Enterprise-Bibliothek, um die Skripts auszuführen – DkAngelito

Antwort

2

Es gibt einen good investigation by Joshua Flanagan mit Test-Harnisch und die Ergebnisse auf seinem Blog. Es liest sich, als hätte er ein ähnliches Problem wie du es beschreibst.

Es gibt zwei Möglichkeiten dies zu tun, und Sie müssen bewerten, welches für Sie das beste ist und ob es irgendwelche Auswirkungen hat.

  1. Exclictly öffnen und schließen Sie die Datenbankverbindung. Also, anstatt nur die Datenbank mit SqlDatabase zu öffnen, müssen Sie einen SqlConnection erstellen und Open() darauf aufrufen.
  2. Fügen Sie einfach Connection Reset=False zu Ihrer Verbindungszeichenfolge hinzu. Ich kenne die Vor- und Nachteile dieses Ansatzes jedoch nicht, also weiß nicht, ob es irgendwelche Nebenwirkungen davon gibt, wie ich verstehe, kann dies Verbindungspooling deaktivieren. Sie werden es besser wissen als ich im Rahmen Ihrer Anwendung/Ihres Utilities.

Ich empfehle, the blog article für alle blutigen Details zu lesen, dann machen Sie ein bisschen herum gräbt, um zu sehen, welches das Beste für Sie ist.

2

Ich würde sagen, analysieren Sie die USE [Datenbank], und speichern Sie es. Fügen Sie es dann am Anfang jeder neuen Abfragezeichenfolge hinzu, sobald alles zusammengefügt ist. Wie so:

using (StreamReader reader = new StreamReader(databaseScriptFile)) 
     { 
      DatabaseFactory.CreateDatabase(); 
      Database db = new SqlDatabase(connectionstring); 
      txbuilder = new StringBuilder(); 
      bool lastExecute = true; 
      string useDB = ""; 
      while (!reader.EndOfStream) 
      { 
       text = reader.ReadLine(); 
       if (text.Substring(0, 3) == "USE") 
       { 
        useDB = text; 
       } 
       else if (text.Trim().ToUpper() != "GO") 
       { 
        lastExecute = false; 
        txbuilder.AppendLine(text); 
       } 
       else 
       { 
        lastExecute = true; 
        strQuery = useDB + txbuilder.ToString(); 
        db.ExecuteNonQuery(CommandType.Text, strQuery); 
        txbuilder.Length = 0; 
       } 
      } 
      //Make sure that the last sentence is executed 
      if (!lastExecute) 
       db.ExecuteNonQuery(CommandType.Text, txbuilder.ToString()); 
     } 

Beachten Sie, dass, wenn die Zeile eine USE [database] ist, es setzt sie in useDB und nicht fügen Sie es Ihrer txbuilder Variable. Jedes Mal, wenn Sie txbuilder "gefüllt" haben, hängen Sie useDB und es zusammen in strQuery an und führen Sie die Abfrage aus. Jede Abfrage beginnt dann mit "USE [Datenbankname]" ...

Auch jedes Mal, wenn Sie eine neue USE drücken, wird auf die Verwendung dieser db umgeschaltet.