2009-10-08 15 views
10

Non riesco a eseguire SQL che crea un database utilizzando un oggetto DbCommand. Che cosa sto facendo di sbagliato? Ecco il mio codice:Come eseguire SQL con commenti e istruzioni GO utilizzando SqlConnection?

DbConnection connection; // initialized and opened elsewhere 
DbCommand cmd = connection.CreateCommand(); 
cmd.CommandText = sql; 
cmd.ExecuteNonQuery(); 

Ecco l'errore:

The query syntax is not valid., near term '/', line 1, column 2. Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Data.EntitySqlException: The query syntax is not valid., near term '/', line 1, column 2.

Ecco la prima parte del file. L'eccezione viene generata per quanto riguarda solo i commenti sulla prima riga:

/****** Object: Table [dbo].[User] Script Date: 10/08/2009 12:14:29 ******/ 
SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE TABLE [dbo].[User](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [FirstName] [nvarchar](50) NULL, 
    [LastName] [nvarchar](50) NULL, 
    [EmailAddress] [nvarchar](100) NULL, 
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

Questo stesso script SQL eseguito bene da SQL Management Studio Express (in realtà tale applicazione ha generato questo script!). È solo la visualizzazione delle query di Server Explorer di Visual Studio e dal mio codice che sembra fallire.

+1

Nota: GO non è un comando SQL, si tratta di un comando per lo strumento client (come OSQL, Query Analyzer, o in questo caso SMSS.) Per rompere lo script in lotti separati" ". Ogni lotto è una chiamata separata al server. –

+0

Possibile duplicato di [Esegui uno script SQL di grandi dimensioni (con comandi GO)] (http://stackoverflow.com/questions/40814/execute-a-large-sql-script-with-go-commands) –

risposta

11

È necessario utilizzare le classi di gestione SQL anziché il normale SqlCommand. This page shows you how to do it. Se cerchi di analizzare da solo l'SQL, ci saranno sempre casi limite che ti mancheranno. Ad esempio, cosa succede se una stringa all'interno del codice contiene la parola "GO" con i ritorni a capo iniziali e finali?

aggiungere questi riferimenti:

  • Microsoft.SqlServer.Smo
  • Microsoft.SqlServer.ConnectionInfo
  • Microsoft.SqlServer.Management.Sdk.Sfc (Edit: non è necessaria Questo riferimento)

quindi è possibile utilizzare questo codice:

string connectionString, scriptText; 
SqlConnection sqlConnection = new SqlConnection(connectionString); 
ServerConnection svrConnection = new ServerConnection(sqlConnection); 
Server server = new Server(svrConnection); 
server.ConnectionContext.ExecuteNonQuery(scriptText); 
+0

Impressionante. Non ho trovato l'assembly 'Microsoft.SqlServer.Management.Sdk.Sfc' per fare riferimento, ma si è scoperto che non era comunque necessario. –

8

Ecco un frammento di codice che ho posted on my blog po 'di tempo fa, che può risolvere questo problema:

private static void RunScript(SqlConnection connection, string script) 
{ 
    Regex regex = new Regex(@"\r{0,1}\nGO\r{0,1}\n"); 
    string[] commands = regex.Split(script); 

    for (int i = 0; i < commands.Length; i++) 
    { 
     if (commands[i] != string.Empty) 
     { 
      using(SqlCommand command = new SqlCommand(commands[i], connection)) 
      { 
       command.ExecuteNonQuery(); 
       command.Dispose(); 
      } 
     } 
    } 
} 

si divide lo script SQL in comandi separati ed esegue ciascuno di essi. Lo uso regolarmente per configurare database di test con script SQL generati.

+0

+1, ma Non penso che questo sia il solo problema qui. L'errore si sta lamentando del commento in cima al file. –

+0

@Joel: Penso che * potrebbe * essere che in realtà si lamenta della dichiarazione completa, che inizia con il commento. Non posso esserne sicuro, quindi ho modificato il testo per essere meno sicuro se fornisce una soluzione o meno. –

+0

il separatore di lotti GO è valido per spazio bianco, almeno in SMSS per SQL Server 2005. –

1

Trovo strano che si stanno ottenendo un EntitySqlException ...

Un'altra soluzione che si può scegliere, è quello di eseguire questo script tramite lo strumento da riga di comando osql. È possibile creare un'istanza System.Diagnostics.Process e utilizzare questa procedura per chiamare osql, che a sua volta esegue lo script.

System.Diagnostics.Process p = new System.Diagnostics.Process(); 

p.StartInfo.FileName = Environment.GetEnvironmentVariable ("COMSPEC"); 
p.StartInfo.UseShellExecute = false; 
p.StartInfo.ErrorDialog = false; 

p.StartInfo.CreateNoWindow = true; 
p.StartInfo.RedirectStandardInput = true; 
p.StartInfo.RedirectStandardError = true; 
p.StartInfo.RedirectStandardOutput = true; 

p.Start(); 

p.StandardInput.WriteLine ("echo off"); 
string command = @"osql -U -b -e -S " + servername + " -d " + databasename + " -i \'" + filename + "\'"; 
p.StandardInput.WriteLine (command); 
p.StandardInput.WriteLine ("exit"); 

p.WaitForExit(); 
+0

Grazie per il suggerimento. Questo può rivelarsi utile in un altro mio scenario. –

0

in SQL Server è possibile concatenare come molte domande come si desidera con un semplice separatore di spazio ma per questo è necessario rimuovere il s "GO".
esempio:

BEGIN TRANSACTION SET QUOTED_IDENTIFIER ON SET ARITHABORT ON SET NUMERIC_ROUNDABORT OFF SET CONCAT_NULL_YIELDS_NULL ON SET ANSI_NULLS ON SET ANSI_PADDING ON SET ANSI_WARNINGS ON COMMIT BEGIN TRANSACTION $remove this GO here$ CREATE TABLE dbo.Tmp_Tralala( ERRID numeric (18,0) NOT NULL)) ON [PRIMARY] $remove this GO here$ IF EXISTS(SELECT * FROM dbo.Tralala) EXEC('INSERT INTO ..etc 
Problemi correlati