tags:

views:

289

answers:

3

I and trying to create a method to run a .sql file on an SQL Server database.

The code i have is:

SqlConnection dbCon = new SqlConnection(connstr);
FileInfo file = new FileInfo(Server.MapPath("~/Installer/JobTraksDB.sql"));
StreamReader fileRead = file.OpenText();
string script = fileRead.ReadToEnd();
fileRead.Close();

SqlCommand command = new SqlCommand(script, dbCon);
try
{
    dbCon.Open();
    command.ExecuteNonQuery();
    dbCon.Close();
}
catch (Exception ex)
{
    throw new Exception("Failed to Update the Database, check your Permissions.");
}

But i keep getting errors about "incorrect syntax near keyword 'GO'" My SQL File starts like this: (Generated from SQL Management Studio)

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Job_Types](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
 CONSTRAINT [PK_JobTypes] 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
SET ANSI_PADDING OFF
GO

How should i be executing this script?

+4  A: 

GO is not a T-SQL statement. It's a hint for client tools such as sqlcmd or Management Studio to split up statements and send them as individual batches. They use a GO command on its own line as a marker to indicate the end of a batch. You shouldn't send the file as a whole to SQL Server.

Side note: There's a File.ReadAllText method that you can use instead of those three lines.

Mehrdad Afshari
ok, then whats the best way to perform a batch create table function? (this is for a web installer)
d1k_is
The naive way is to split the file by lines containing the `GO` command and send each part to SQL Server in a loop. However, I think you are reinventing the wheel as some open source projects (e.g. DotNetNuke) use a similar technique for their installation. You can check their source out.
Mehrdad Afshari
check my answer. Code sample does the job perfectly.
WowtaH
I know there are a few open source web installers out there but this is pretty much all i need it to do... thanks for your answers guys!
d1k_is
+2  A: 

This is how we do it:

    protected virtual void ExecuteScript(SqlConnection connection, string script)
    {
        string[] commandTextArray = System.Text.RegularExpressions.Regex.Split(script, "\r\n[\t ]*GO");

        SqlCommand _cmd = new SqlCommand(String.Empty, connection);

        foreach (string commandText in commandTextArray)
        {
            if (commandText.Trim() == string.Empty) continue;
            if ((commandText.Length >= 3) && (commandText.Substring(0, 3).ToUpper() == "USE"))
            {
                throw new Exception("Create-script contains USE-statement. Please provide non-database specific create-scripts!");
            }

            _cmd.CommandText = commandText;
            _cmd.ExecuteNonQuery();
        }

    }

Load the contents of your script using some file-reading function.

WowtaH
I can see a bug: Assume I have a procedure named `sp` and the script is `"sp"`. `commandText.Substring(0, 3)` will throw an `IndexOutOfRangeException`.
Mehrdad Afshari
@Mehrdad: Yes, common mistake, assuming that String.Substring(0, xxx) works exactly like the VB function Left(xxx). :-)
Christian Hayter
@WowtaH: Apart from that, nicely done. :-)
Christian Hayter
Thanks... I fixed the bug :)
WowtaH
A: 

If you are willing to include a couple of the SMO dlls, you can execute a script with a few lines of code:

using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

    public void Exec(string script)
    {
        using (var conn = new SqlConnection(ConnString))
        {
            var server =  new Server(new ServerConnection(conn));
            server.ConnectionContext.ExecuteNonQuery(script, ExecutionTypes.ContinueOnError);
        }
    }

The SMO library handles the GO issue so you don't have to. You will need to reference the following assemblies:

Microsoft.SqlServer.ConnectionInfo.dll

Microsoft.SqlServer.Management.Sdk.Sfc.dll

Microsoft.SqlServer.Smo.dll

Todd Stout