如何从C#执行.sql?

如何从C#执行.sql?,c#,sql,sql-server,sql-server-2008,C#,Sql,Sql Server,Sql Server 2008,对于一些集成测试,我希望连接到数据库并运行一个.sql文件,该文件具有实际运行测试所需的模式,包括GO语句。如何执行.sql文件?(或者这完全是错误的选择?) 我发现显示此代码: using System.Data.SqlClient; using System.IO; using Microsoft.SqlServer.Management.Common; using Microsoft.SqlServer.Management.Smo; namespace ConsoleApplicati

对于一些集成测试,我希望连接到数据库并运行一个.sql文件,该文件具有实际运行测试所需的模式,包括GO语句。如何执行.sql文件?(或者这完全是错误的选择?)

我发现显示此代码:

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: 异常已由 调用的目标。--> System.TypeInitializationException: “”的类型初始值设定项 引发了异常。--> .模块异常: C++模块在加载期间失败 appdomain初始化。--> System.DllNotFoundException:无法删除 加载DLL“MSVCR80.DLL”:指定的 找不到模块。(例外情况 来自HRESULT:0x8007007E)

我被告知从某个地方去下载那个DLL,但这听起来非常骇人听闻。有没有更干净的方法?还有别的办法吗?我做错了什么


我正在使用Visual Studio 2008、SQL Server 2008、.Net 3.5SP1和C#3.0执行此操作。

您是否尝试过在.SQL文件中使用非常基本的脚本来运行此操作?可能只是插入一行或创建任意表?很容易验证的东西?从本质上讲,这段代码就像是对sql进行硬编码,只是您从文件中读取它。如果您可以让它使用一个非常简单的文件,那么我会说文件结构本身可能有问题。这篇帖子暗示了这样一个事实,即关于什么可以和什么不能在文件中有一些规定。如果没有别的,它是一个开始故障排除的好地方。

MSVCR80是Visual C++ 2005运行时。您可能需要安装运行时软件包。有关更多详细信息,请参阅

除了解决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
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 -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
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);
执行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
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工具的更多信息,请参阅

using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
您不应该需要SMO来执行查询。尝试改用SqlCommand对象。使用语句删除这些内容。使用以下代码执行查询:

 SqlConnection conn = new SqlConnection(sqlConnectionString);
 SqlCommand cmd = new SqlCommand(script, conn);
 cmd.ExecuteNonQuery();
另外,删除对SMO的项目引用。注意:您需要正确清理资源

更新: ADO.NET库。看起来您的选项如下:

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

  • 事实上,在这种情况下,我认为SMO可能是最好的选择,但您需要找出未找到dll的原因。

    您可能对以下内容感兴趣:


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

    如果在项目中添加以下引用,则原始代码可以正常工作

    我使用SQL2008Express

    路径: C:\ProgramFiles(x86)\Microsoft SQL Server\100\SDK\Assembly\

    档案:
    microsoft.sqlserver.smo.dll、microsoft.sqlserver.connectioninfo.dll和microsoft.sqlserver.Management.Sdk.Sfc.dll都需要从代码中自动运行生成的数据库脚本,我开始解析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 Server本身导出的,没有手动生成的内容,因此应该是有效的。邮报说,如果文件有go语句,这是运行它的唯一方法,这就是我这么做的原因。我用select(1+1)替换了文件的内容,得到了完全相同的错误。我不认为这是SQL错误。有没有办法运行一个SQL文件,而不需要安装一个旧VisualC++?运行时,我需要使用什么文件,我想这是我的.MDF文件。right@Anjali:所讨论的文件是SQL文件。@DavidAndres:file参数-i,它能包含空格吗?@Tony_Kilopamikegolf:不像上面使用的那样,但我怀疑用双引号将文件名括起来会很好。Matt,非常可靠。在我现在正在进行的一个项目中,我们的代码使用Smo的方式与OP中描述的完全相同。我不明白为什么SqlCommand更适合…直到我阅读了您的答案。如果SQL文件包含“GO”语句,这是否有效?我的理解是它没有,我还没有测试过。我相信是的,不是的。从SQL server导出的架构中有许多东西使用这种方法失败:测试方法IsitScienceEffect.Tests.UserTest.TestMethod1引发异常:System.Data.SqlClient.SqlException:不正确