SQL Server 如何从C#执行.sql?

db2dz4w8  于 2023-01-08  发布在  C#
关注(0)|答案(6)|浏览(201)

对于某些集成测试,我希望连接到数据库并运行一个. sql文件,该文件包含测试实际运行所需的模式,包括GO语句。我如何执行. sql文件?(或者这是完全错误的方法吗?)
我发现a post in the MSDN forum显示以下代码:

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.TypeInitializationException:""的类型初始值设定项引发异常。---〉. ModuleLoadException:C++模块在appdomain初始化期间加载失败。---〉系统。DllNotFoundException:无法加载DLL "MSVCR80.dll":找不到指定的模块。(HRESULT异常:0x8007007E)。
我被告知从某个地方下载这个DLL,但这听起来很笨拙。有没有更干净的方法?有没有其他方法?我做错了什么?
我正在用Visual Studio 2008、SQL Server 2008、. Net 3.5SP1和C#3.0来做这件事。

bakd9h0s

bakd9h0s1#

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库do not support the 'GO' keyword。您的选项似乎为:
1.分析脚本。删除"GO"关键字并将脚本拆分为单独的批处理。将每个批处理作为其自己的SqlCommand执行。
1.将脚本发送到shell中的SQLCMD(David Andres的答案)。
1.像博客文章中的代码一样使用SMO。
实际上,在这种情况下,我认为SMO可能是最好的选择,但您需要跟踪为什么找不到dll。

0g0grzrc

0g0grzrc2#

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

af7jpaap

af7jpaap3#

由于同样需要自动运行从代码生成的数据库脚本,我开始解析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,执行起来没有问题。

iyfamqjs

iyfamqjs4#

你有没有试过在.sql文件中用一个非常非常基本的脚本来运行它?也许只是插入一行或者创建一个任意的表?或者是非常容易验证的东西?本质上,这段代码就像是对sql进行硬编码,只是你是从一个文件中阅读它。如果你能让它在一个非常简单的文件中工作,那么我会说,可能是文件结构本身有问题。2这篇文章间接提到了这样一个事实,即文件中有一些关于什么可以和什么不可以的规定。3如果没有别的,这是一个开始排除故障的好地方。

8ehkhllq

8ehkhllq5#

如果您在项目中添加以下引用,则原始代码将正常工作。
我使用SQL 2008 Express。
路径:C:\程序文件(x86)\Microsoft SQL Server\100\软件开发工具包\程序集
文件:Microsoft.sql服务器. smo.dll、Microsoft.sql服务器.连接信息. dll和Microsoft.sql服务器.管理. sdk.sfc.dll

pgvzfuti

pgvzfuti6#

您可能对此感兴趣:Link
它提供了一个通用的“测试装置”来自动执行sql脚本。也有可用的示例代码,并且没有任何不寻常的程序集依赖...

相关问题