【问题标题】:How do I run my .sql script file through ADO.NET?如何通过 ADO.NET 运行我的 .sql 脚本文件?
【发布时间】: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 语句时出现异常。我该如何解决这个问题?

【问题讨论】:

    标签: asp.net sql ado.net


    【解决方案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 运行时中加载。”见:stackoverflow.com/questions/1604663/…
        【解决方案4】:

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

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

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2011-03-30
            • 2020-09-30
            • 2018-08-01
            • 1970-01-01
            • 2021-06-04
            • 2012-08-19
            相关资源
            最近更新 更多