在交易中使用“GO”
我正在构build一个Web应用程序,试图在App_Start上安装/升级数据库。 安装程序的一部分是确保数据库安装了asp.netfunction。 为此,我正在使用System.Web.Management.SqlServices对象。
我的意图是做一个SQL事务中的所有数据库工作,如果有任何失败,回滚事务并保持数据库不变。
SqlServices对象有一个方法“安装”,它需要一个ConnectionString而不是一个事务。 所以相反,我使用SqlServices.GenerateApplicationServicesScripts如下所示:
string script = SqlServices.GenerateApplicationServicesScripts(true, SqlFeatures.All, _connection.Database); SqlHelper.ExecuteNonQuery(transaction, CommandType.Text, script, ...);
然后使用企业库中的SqlHelper。
但是这会抛出一个exception与一个错误的对接,一些在下面
Incorrect syntax near 'GO'. Incorrect syntax near 'GO'. Incorrect syntax near 'GO'. Incorrect syntax near 'GO'. Incorrect syntax near the keyword 'USE'. Incorrect syntax near the keyword 'CREATE'. Incorrect syntax near 'GO'. The variable name '@cmd' has already been declared. Variable names must be unique within a query batch or stored procedure.
我假设这是在SQL事务中使用GO语句的一些问题。
我怎样才能让这个生成的脚本以这种方式执行工作。
GO不是一个SQL关键字。
这是客户端工具(如SSMS)使用的批处理分隔符,将整个脚本分成多个批次
你必须自己分解脚本,或者使用像“-c GO”或osql这样的sqlcmd来处理“GO”
我只想补充一点,如果你为交易命名,你可以在其中包含多个GO部分,它们将作为一个整体回滚。 如:
BEGIN TRANSACTION TransactionWithGos; GO SET XACT_ABORT ON; -- Roll back everything if error occurs in script GO -- do stuff GO COMMIT TRANSACTION TransactionWithGos; GO
穷人的方法来解决这个问题:拆分GO语句上的SQL。 就像是:
private static List<string> getCommands(string testDataSql) { string[] splitcommands = File.ReadAllText(testDataSql).Split(new string[]{"GO\r\n"}, StringSplitOptions.RemoveEmptyEntries); List<string> commandList = new List<string>(splitcommands); return commandList; }
[这实际上是从我正在处理的应用程序中复制出来的。 这个代码让我感到害怕]
然后只是在列表上执行ExecuteNonQuery()
。 花哨和使用交易奖励积分。
#####奖金分数######
如何处理交易位真的取决于运营目标。 基本上你可以做到这一点:
a)将整个执行包裹在一个单独的事务中,如果你真的想要所有的执行都执行或失败(更好的select恕我直言)
b)将每个调用包装到ExecuteNonQuery()
中。 那么实际上,每个电话都是自己的交易。 但你可以抓住例外,继续下一个项目。 当然,如果这是典型的生成DDL的东西,往往下一部分取决于以前的一部分,所以一部分失败可能会扰乱整个狗。
编辑指出下面我指定的tran批次其实是正确的。
问题不在于GO不能在事务中使用GO,GO代表批处理结束,而本身不是T-SQL命令。 您可以使用SQLCMD执行整个脚本,也可以在GO上分割并依次执行每个批处理。
testing你的脚本:
- 恢复备份服务器上的生产备份
- 用GO运行运行脚本
安装你的脚本:
- closures应用程序
- 转到单用户模式
- 备份数据库
- 使用GO运行脚本,失败恢复备份
- 回到多用户模式
- 重启应用程序
实际上,当您使用Microsoft.SqlServer.Management.Smo扩展名时,您可以使用GO语句:
var script = GetScript(databaseName); var conn = new SqlConnection(connectionString.ConnectionString); var svrConnection = new ServerConnection(conn); var server = new Server(svrConnection); server.ConnectionContext.ExecuteNonQuery(script);
http://msdn.microsoft.com/de-de/library/microsoft.sqlserver.management.smo.aspx
您只需要从以下url部署SQL CLRtypes和SQLpipe理对象包: http : //www.microsoft.com/en-us/download/details.aspx?id=29065 (SQL 2012版)
只是想我会在这里添加我的解决scheme…用ExecuteNonQuery可理解的分隔符replace“GO”,即';' 运营商。 使用这个函数来修复你的脚本:
private static string FixGoDelimitedSqlScript(string script) { return script.Replace("\r\nGO\r\n", "\r\n;\r\n"); }
它可能不适用于复杂嵌套的T-SQL';' 在他们的操作员,但为我和我的脚本工作。 我会使用上面列出的拆分方法,但是我被我使用的库限制,所以我不得不寻找另一种解决方法。 希望这可以帮助别人!
PS。 我知道,';' 运算符是语句分隔符,“GO”运算符是批处理分隔符,所以任何高级脚本可能都不会被修复。