如何从C#执行.sql?
对于一些集成测试,我希望连接到数据库并运行一个.sql文件,该文件具有实际运行测试所需的模式,包括GO语句。如何执行.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
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库。看起来您的选项如下:
事实上,在这种情况下,我认为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:不正确