获取错误消息,但继续在SMO中执行

时间:2019-01-31 02:42:02

标签: c# sql sql-server smo

我正在重写用于在数据库上运行升级的应用程序。基本上,该应用程序的想法是需要一堆脚本(每个版本一个),并在数据库的当前版本和它具有的最新版本之间运行每个脚本。我试图为我们找到一种更好的方式来处理此过程,并且试图使SQL管理对象按照我们需要的方式工作。供参考,这是我必须处理的限制。

  • 它必须处理GO语句(SMO可以做到)
  • 它不能要求我们修改我们拥有的文件。 (这将用于数百甚至数千个文件,我们不想手动编辑其中的每个文件,因此添加try catch完全是不可能的)
  • 如果遇到错误,它必须继续执行下一个GO语句。这主要是为了匹配我们当前应用程序的工作方式。如果在一批脚本中遇到错误,我们希望它继续到下一个脚本,因为大多数情况下它们是不相关的。
  • 如果脚本遇到错误,则必须输出错误消息,以便用户可以知道版本的升级无效,因此开发人员可以为下一个版本纠正错误(这是问题所在)

这是我目前作为代码使用的内容:

string messages = "";

private void button1_Click(object sender, EventArgs e)
{
    string setup = File.ReadAllText(@"[redacted]\Setup.sql");
    string script = File.ReadAllText(@"[redacted]\6.3.6002.0.sql");
    string script2 = File.ReadAllText(@"[redacted]\6.3.6003.0.sql");

    var cnx = new SqlConnection(/*proper connection string*/);

    var server = new Server(new ServerConnection(cnx));
    //server.ConnectionContext.InfoMessage += ConnectionContext_InfoMessage;
    server.ConnectionContext.ServerMessage += ConnectionContext_ServerMessage;

    server.ConnectionContext.ExecuteNonQuery(setup);
    server.ConnectionContext.ExecuteNonQuery(script);
    server.ConnectionContext.ExecuteNonQuery(script2, ExecutionTypes.ContinueOnError);

    txtResult.Text = messages;
}

private void ConnectionContext_ServerMessage(object sender, ServerMessageEventArgs e)
{
    messages += e.Error.Message + "\r\n";
}

这是我正在使用的脚本:

Setup.sql:

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'UPGRADE_HISTORY')
DROP TABLE UPGRADE_HISTORY

IF EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'TEST_CODE_TABLE')
    DROP TABLE TEST_CODE_TABLE

CREATE TABLE UPGRADE_HISTORY (
    UPDATE_DATE     DATE            NOT NULL,
    VERSION_TXT     VARCHAR(50)     NOT NULL,
    PRIMARY KEY     (UPDATE_DATE, VERSION_TXT)
)

CREATE TABLE TEST_CODE_TABLE (
    CODE_VALUE      INT             PRIMARY KEY,
    DESCRIPTION_TXT VARCHAR(250)    NOT NULL        
)

INSERT INTO UPGRADE_HISTORY VALUES
(DATEADD(d, -3, GETDATE()), '6.2.5000'),
(DATEADD(d, -1, GETDATE()), '6.2.5001'),
(DATEADD(d, -1, GETDATE()), '6.2.5002'),
(DATEADD(d, -1, GETDATE()), '6.3.6000.0'),
(DATEADD(d, -1, GETDATE()), '6.3.6001.0')

INSERT INTO TEST_CODE_TABLE VALUES
(1001, 'Test Code Table'),
(1002, 'Test Code Table 2')

6.3.6602.0.sql:

INSERT INTO UPGRADE_HISTORY VALUES
(GETDATE(), '6.3.6001.0')

GO

PRINT 'Test Code Table Change'
GO

UPDATE TEST_CODE_TABLE SET DESCRIPTION_TXT = 'Test Code Table Change' WHERE CODE_VALUE = 1002;
GO

6.3.6003.0.sql:

INSERT INTO UPGRADE_HISTORY VALUES
(GETDATE(), '6.3.6003.0')

GO

PRINT 'Test Error'
GO

INSERT INTO CODE_TABLE VALUES (1001, 'Test') 

--This will throw an error since this will conflict with the primary key
--of the code table (or you know, because I just noticed it doesn't call
--the right table, it's really relevant since I want it to throw an  
--error, w/e what it is)

GO

PRINT 'Second Test Code Table Change'
GO

UPDATE TEST_CODE_TABLE SET DESCRIPTION_TXT = 'Test Code Table Change 2' WHERE CODE_VALUE = 1002;

--We still want this to execute.    

GO

这是为了重现我们的更新中可能发生的情况。因此,实际上,设置只是每次都创建重新创建数据库,因此我可以使用相同的脚本,然后第一个升级文件是模拟按预期功能运行的文件,最后是第二个升级文件是模拟升级有错误的文件。这就是问题开始的地方。就目前而言,当我执行第二个脚本时,第一部分运行,然后第二部分运行并出现错误,但我没有收到错误消息。 InfoMessageServerMessage事件均不会触发。然后,运行第三部分(出错的语句之后的部分),然后得到用于打印的ServerMessage。作为参考,这是我收到的输出:

Test Code Table Change
Test Error
Second Test Code Table Change

错误发生前后的打印,我可以通过仔细检查数据来确认错误之后的UPDATE语句也已执行。但是,不会因INSERT语句引发错误的事实而引发任何消息或错误。我们确实需要SMO引发错误,或者触发ServerMessage事件,或者其他任何事情。是我缺少的东西,还是该框架的缺点。

0 个答案:

没有答案