Domanda

I eseguire script SQL per modificare lo schema del database. Sembra qualcosa di simile a questo:

using (var command = connection.CreateCommand())
{
    command.CommandText = script;
    command.ExecuteNonQuery();
}

Inoltre, i comandi vengono eseguiti all'interno di una transazione.

Gli sguardi scrip come questo:

Alter Table [TableName]
ADD [NewColumn] bigint NULL

Update [TableName]
SET [NewColumn] = (SELECT somevalue FROM anothertable)

ottengo un errore, perché NewColumn non esiste. Sembra di analizzare e convalidarlo prima che venga eseguito.

Quando eseguo tutta la roba in Management Studio, posso mettere GO tra le dichiarazioni, allora funziona. Quando ho messo GO nella sceneggiatura, ADO.NET lamenta (sintassi non corretta in prossimità 'GO').

ho potuto dividere lo script in script separati ed eseguirlo in comandi separati, questo sarebbe difficile da gestire. Potrei dividere su ogni GO, parsing dello script stesso. Penso solo che ci dovrebbe essere una soluzione migliore e che non ho capito qualcosa. Come devono essere eseguiti gli script come questo?


La mia realizzazione, se qualcuno è interessato a, secondo la risposta di John Saunders':

List<string> lines = new List<string>();
while (!textStreamReader.EndOfStream)
{
    string line = textStreamReader.ReadLine();
    if (line.Trim().ToLower() == "go" || textStreamReader.EndOfStream)
    {
        ExecuteCommand(
            string.Join(Environment.NewLine, lines.ToArray()));

        lines.Clear();
    }
    else
    {
        lines.Add(line);
    }
}
È stato utile?

Soluzione

Si deve eseguire ogni lotto separatamente. In particolare, per eseguire uno script che può contenere più lotti ( "GO" parole chiave), si deve dividere lo script sulle parole chiave "Go".

Non testato:

string script = File.ReadAllText("script.sql");
string[] batches = script.Split(new [] {"GO"+Environment.NewLine}, StringSplitOptions.None);
foreach (string batch in batches)
{
    // run ExecuteNonQuery on the batch
}

Altri suggerimenti

Non utilizzando uno dei librerie ORM mille per farlo? Buono: -)

Per essere completamente sicuri durante l'esecuzione di script che fanno cambiamenti strutturali utilizzano SMO piuttosto che SqlClient e assicurarsi che Marte non è attivata tramite stringa di connessione (SMO normalmente si lamentano se è comunque). Cercare ServerConnection di classe e ExecuteNonQuery - diverse DLL ovviamente: -)

Il diff è che SMO dll pases lo script come-è quello di SQL quindi è genuino equivalente di correre in SSMS o tramite riga di cmd isql. Affettare il GO-s finisce per crescere in scansione molto più grande ogni volta che si incontra un altro problema tecnico (come quella GO può essere nel mezzo di un commento multi-linea, non ci può essere più istruzioni USE, uno script può essere caduta la stessa DB SqlClient collegato a - oops :-). Ho appena ucciso una cosa del genere nella base di codice che ho ereditato (dopo gli script più complessi in conflitto con Marte e Marte è un bene per il codice di produzione, ma non per le cose admin).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top