如何从C#执行.sql?

对于某些集成测试,我想连接到数据库并运行.sql文件,该文件具有测试实际运行所需的模式,包括GO语句。 我怎么能执行.sql文件? (或者这完全是错误的方式?)

我在MSDN论坛中发现了一条显示此代码的post :

using System.Data.SqlClient; using System.IO; using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Smo; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string sqlConnectionString = "Data Source=(local);Initial Catalog=AdventureWorks;Integrated Security=True"; FileInfo file = new FileInfo("C:\\myscript.sql"); string script = file.OpenText().ReadToEnd(); SqlConnection conn = new SqlConnection(sqlConnectionString); Server server = new Server(new ServerConnection(conn)); server.ConnectionContext.ExecuteNonQuery(script); } } } 

但在最后一行我收到此错误:

System.Reflection.TargetInvocationException:调用目标抛出了exception。 —> System.TypeInitializationException:”的类型初始值设定项引发exception。 —> .ModuleLoadException:在appdomain初始化期间无法加载C ++模块。 —> System.DllNotFoundException:无法加载DLL’MSVCR80.dll’:找不到指定的模块。 (来自HRESULT的exception:0x8007007E)。

我被告知要从某个地方下载该DLL,但这听起来非常h​​acky。 有更干净的方式吗? 还有另一种方法吗? 我究竟做错了什么?

我正在使用Visual Studio 2008,SQL Server 2008,.Net 3.5SP1和C#3.0。

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

您不应该需要SMO来执行查询。 请尝试使用SqlCommand对象。 删除这些using语句。 使用此代码执行查询:

  SqlConnection conn = new SqlConnection(sqlConnectionString); SqlCommand cmd = new SqlCommand(script, conn); cmd.ExecuteNonQuery(); 

另外,删除对SMO的项目引用。 注意:您需要正确清理资源。

更新:

ADO.NET库不支持“GO”关键字 。 看起来你的选择是:

  1. 解析脚本。 删除“GO”关键字并将脚本拆分为不同的批次。 将每个批处理作为自己的SqlCommand执行。
  2. 将脚本发送到shell中的SQLCMD(David Andres的回答)。
  3. 像博客文章中的代码一样使用SMO。

实际上,在这种情况下,我认为SMO可能是最好的选择,但是你需要找出为什么没有找到dll。

MSVCR80是Visual C ++ 2005运行时。 您可能需要安装运行时包。 有关详细信息,请参阅http://www.microsoft.com/downloads/details.aspx?FamilyID=200b2fd9-ae1a-4a14-984d-389c36f85647&displaylang=en 。

除了解决DLL问题和Matt Brunell的答案(我认为它更适合您正在尝试做的事情)之外,您还可以使用SQLCMD命令行工具(来自SQL客户端工具安装)来执行这些SQL脚本。 请确保它在您的路径上,这样您就不会对路径位置感到困难。

这将是这样的:

实际命令:

 SQLCMD -S myServer -D myDatabase -U myUser -P myPassword -i myfile.sql 

参数(案例事项):

 S: server d: database U: User name, only necessary if you don't want to use Windows authentication P: Password, only necessary if you don't want to use Windows authentication i: File to run 

执行SQL文件的代码:

 var startInfo = new ProcessStartInfo(); startInfo.FileName = "SQLCMD.EXE"; startInfo.Arguments = String.Format("-S {0} -d {1}, -U {2} -P {3} -i {4}", server, database, user, password, file); Process.Start(startInfo); 

有关SQLCMD工具的更多信息,请参见http://msdn.microsoft.com/en-us/library/ms162773.aspx 。

由于需要从代码中自动运行生成的数据库脚本,我开始解析SQL脚本以删除GO语句并将脚本拆分为单独的命令(如@MattBrunell所建议的那样)。 删除GO语句很容易,但拆分"\r\n"上的语句不起作用,因为搞砸了多行语句。 测试一些不同的方法,我很惊讶地发现脚本根本不必拆分成单独的命令。 我刚刚删除了所有“GO”语句,并将整个脚本(包括注释)发送到SqlCommand:

  using System.Data.SqlClient; using(SqlConnection connection = new SqlConnection(connectionString)) using(SqlCommand command = connection.CreateCommand()) { string script = File.ReadAllText("script.sql"); command.CommandText = script.Replace("GO", ""); connection.Open(); int affectedRows = command.ExecuteNonQuery(); } 

此代码已使用SQL Server 2008 R2和“数据库 – >任务 – >生成脚本…”生成的脚本进行了测试。 以下是脚本中命令的一些示例:

 USE [MyDatabase] ALTER TABLE [MySchema].[MyTable] DROP CONSTRAINT [FK_MyTable_OtherTable] DROP TABLE [MySchema].[MyTable] SET ANSI_NULLS ON SET QUOTED_IDENTIFIER ON /****** Object: Table [MySchema].[MyTable] Script Date: 01/23/2013 13:39:29 ******/ CREATE TABLE [MySchema].[MyTable]( [Id] [int] IDENTITY(1,1) NOT NULL, [Subject] [nvarchar](50) NOT NULL, [Body] [nvarchar](max) NOT NULL, CONSTRAINT [PK_MyTable] 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] SET IDENTITY_INSERT [MySchema].[MyTable] ON INSERT [MySchema].[MyTable] ([Id], [Subject], [Body]) VALUES (1, N'MySubject', N'Line 1 Line 2 Line 3 Multi-line strings are also OK. ') SET IDENTITY_INSERT [MySchema].[MyTable] OFF 

我猜单个SqlCommand可能有一些最大长度,超过该长度必须拆分脚本。 我的脚本执行没有问题,包含大约1800个语句,为520 kB。

您是否尝试使用.sql文件中非常非常基本的脚本运行它? 也许只是插入一行或创建任意表的东西? 什么东西很容易validation? 本质上,这个代码就像对sql进行硬编码一样,除非你从文件中读取它。 如果你可以使用一个非常简单的文件,那么我会说文件结构本身可能有问题。 该帖提到了这样一个事实,即对文件中可以和不可以有的内容有一些规定。 如果不出意外,它是开始排除故障的好地方。

您可能对此感兴趣: http : //geekswithblogs.net/thomasweller/archive/2009/09/08/automating-database-script-execution.aspx

它提供了一个通用的“测试夹具”来自动执行sql脚本。 还有可用的示例代码,并且不依赖于任何不寻常的程序集……

如果您在项目中添加以下引用,那么原始代码将正常工作。

我使用SQL 2008 Express。

路径:C:\ Program Files(x86)\ Microsoft SQL Server \ 100 \ SDK \ Assemblies \

文件:microsoft.sqlserver.smo.dll,microsoft.sqlserver.connectioninfo.dll和Microsoft.SqlServer.Management.Sdk.Sfc.dll