如何通过 ADO.NET 运行我的 .sql 脚本文件?

Posted

技术标签:

【中文标题】如何通过 ADO.NET 运行我的 .sql 脚本文件?【英文标题】:How do I run my .sql script file through ADO.NET? 【发布时间】:2010-11-14 12:25:34 【问题描述】:

我想通过 ADO.NET 使用我的 ASP.NET 网站运行我的 .sql 脚本文件。怎么可能不工作?

当我尝试时

'dbScript is a string and contains contents of the .sql file'
Dim cmd As New SqlCommand(dbScript, con)
Try
    con.Open()
    cmd.ExecuteNonQuery()
Catch ex As Exception
Finally
    con.Close()
    cmd.Dispose()
End Try

在脚本中执行 GO 语句时出现异常。我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

你必须做两遍解析。第一次通过是删除所有 cmets 并构建一个新字符串。第二遍是使用基于 GO 关键字的 REGEX 拆分。

【讨论】:

【参考方案2】:

使用拆分方法执行批处理有一个小问题。问题是cmets。假设您对文件的内容没有权力。你只需要执行它。多行注释中的 GO 将成为此处每个解决方案示例中的问题,即使用“GO”作为分隔符拆分 sql 代码。示例:

[some sql code]
GO

/* start of commented out sql code ***********
[some sql code]
GO
end of commented out sql code ****************/

[some sql code]
GO

这将需要一些比拆分更复杂的解析。这将不再起作用:

Regex regex = new Regex("^GO", RegexOptions.IgnoreCase | RegexOptions.Multiline);
string[] lines = regex.Split(sql);

此代码还忽略了空格可能导致 GO。

【讨论】:

【参考方案3】:

请参阅我关于 Handling GO Separators in SQL - The Easy Way 的博文。诀窍是使用SMO's ExecuteNonQuery() 方法。例如,以下代码将运行目录中的所有脚本,而不管 GO 分隔符如何:

    using System;
    using System.IO;
    using System.Data.SqlClient;
    using System.Collections.Generic;

    //Microsoft.SqlServer.Smo.dll
    using Microsoft.SqlServer.Management.Smo;
    //Microsoft.SqlServer.ConnectionInfo.dll
    using Microsoft.SqlServer.Management.Common;

    public class RunAllSqlSriptsInDirectory
    
        public static void Main()
        
            string scriptDirectory = "c:\\temp\\sqltest\\";
            string sqlConnectionString = "Integrated Security=SSPI;" + 
                "Persist Security Info=True;Initial Catalog=Northwind;Data Source=(local)";
            DirectoryInfo di = new DirectoryInfo(scriptDirectory);
            FileInfo[] rgFiles = di.GetFiles("*.sql");
            foreach (FileInfo fi in rgFiles)
            
                FileInfo fileInfo = new FileInfo(fi.FullName);
                string script = fileInfo.OpenText().ReadToEnd();
                SqlConnection connection = new SqlConnection(sqlConnectionString);
                Server server = new Server(new ServerConnection(connection));
                server.ConnectionContext.ExecuteNonQuery(script);
            
        
    

【讨论】:

请注意,虽然依赖 SMO 将要求您的应用程序预先安装 SMO 可再发行组件,但会带来一点不便。但真正的杀手锏是 SMO 是特定于版本的,并且会完全拒绝连接到更高版本的 SQL:使用 SQL 2k5 中的 SMO 开发的应用程序将无法连接到 SQL Server 2k8,需要开发人员发布新的使用 SMO 2k8 的应用版本。 莱姆斯,好点子。当您在自己的网站上运行脚本时,这些并不是什么大不了的事情,Muhammad 要求这样做。 感谢您的帮助。希望尽快找到通用且独立于平台的解决方案。如果你这样做,请在这里分享。再次感谢 你应该在 using() 中包装 SqlConnection 声明 我发现使用这种技术会导致加载 SMO 库中的一些非托管代码。如果您使用的是 .Net 4.0,您将遇到以下情况:“混合模式程序集是针对运行时的版本‘v2.0.50727’构建的,如果没有额外的配置信息,则无法在 4.0 运行时中加载。”见:***.com/questions/1604663/…【参考方案4】:

这是因为 GO 实际上不是原生的 TSQL 语句,它在 Management Studio/Enterprise Manager 中用于将脚本分批。

您需要: 1) 在每个 GO 语句上将其拆分为多个单独的脚本 2)使用SQL管理对象中的Server类,例如here

【讨论】:

【参考方案5】:

GO 不是 Transact-SQL 语句,是工具批处理分隔符。当批处理中遇到 GO 时,服务器正确地抱怨语法错误。您需要将文件拆分为多个批次,然后执行单个批次。使用正则表达式拆分文件 inot 批次并在单行上识别 GO 不区分大小写。

【讨论】:

以上是关于如何通过 ADO.NET 运行我的 .sql 脚本文件?的主要内容,如果未能解决你的问题,请参考以下文章

ADO.NET Entity Framework 如何查看T

ADO.NET 中参数化 SQL 命令的最终形式

ADO .NET 与 SQL Server Management Studio - ADO 性能更差

我可以判断 ado.net DbCommand 是不是是查询(在执行之前)

VB.NET 2010 和 SQL Server 2008 与 ADO.NET 问题

捕获 ADO.net DB 查询运行时