2009-10-08 83 views
10

我似乎無法執行使用DbCommand對象創建數據庫的SQL。我究竟做錯了什麼?這裏是我的代碼:如何使用SqlConnection執行帶註釋和GO語句的SQL?

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

這裏的錯誤:

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.

下面是該文件的第一部分。拋出異常時就只在第一行的評論:

/****** 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 

同樣的SQL腳本SQL管理Studio Express的執行就好了(事實上該應用產生的這個腳本!)。它只是Visual Studio自己的服務器資源管理器查詢視圖,並且來自我自己的代碼,這似乎失敗了。

+1

注:GO是不是一個SQL命令,它是一個命令至客戶端工具(例如OSQL,查詢分析器,或在這種情況下SMSS。),以打破腳本轉換成單獨的「批」。每批次都是對服務器的單獨調用。 – 2009-10-08 22:24:46

+0

[執行大型SQL腳本(使用GO命令)]的可能副本](http://stackoverflow.com/questions/40814/execute-a-large-sql-script-with-go-commands) – 2016-06-09 02:15:00

回答

11

您需要使用SQL管理類而不是普通的SqlCommand。 This page shows you how to do it.如果你嘗試自己解析SQL,那麼總會有你錯過的邊緣情況。例如,如果代碼中的字符串包含帶前導和尾隨回車符的單詞「GO」會怎麼樣?

添加這些引用:

  • Microsoft.SqlServer.Smo
  • Microsoft.SqlServer.ConnectionInfo
  • Microsoft.SqlServer.Management.Sdk.Sfc(編輯
  • :不需要此參考)

然後你可以使用此代碼:

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

太棒了。我找不到要引用的'Microsoft.SqlServer.Management.Sdk.Sfc'程序集,但事實證明它不是必需的。 – 2009-10-09 03:39:56

8

下面的代碼片段,我posted on my blog前一段時間,可能解決這個問題:

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(); 
      } 
     } 
    } 
} 

它拆分SQL腳本爲單獨的命令並執行它們。我經常使用它來設置生成的SQL腳本的測試數據庫。

+0

+1,但我不認爲這是唯一的問題。錯誤是抱怨文件頂部的註釋。 – 2009-10-08 20:29:30

+0

@Joel:我認爲它*可能是因爲它實際上抱怨了完整的陳述,而這恰恰是從評論開始的。雖然不能確定,所以我編輯過的文字不太確定它是否提供瞭解決方案。 – 2009-10-08 20:36:35

+0

GO批處理分隔符在空白區域有效,至少在SQL Server 2005的SMSS中是有效的。 – 2009-10-08 22:37:56

1

我覺得很奇怪,你得到的EntitySqlException ...

,你可以選擇另一種解決方案,是通過osql命令行工具來執行這個腳本。 您可以創建一個System.Diagnostics.Process實例,並使用此進程調用osql,然後執行腳本。

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

感謝您的提示。這可能在我的另一個場景中證明是有用的。 – 2009-10-09 03:39:01

0

在SQL Server中,只要你想用一個簡單的空間分隔您可以連接儘可能多的查詢,但對於您需要刪除「GO」 S。
例如:

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