如何从 .NET 捕获 SQL 脚本 运行 的输出,包括受影响的行?
How do you capture the output of a SQL Script run from .NET, including rows affected?
考虑这个简单的 SQL 脚本:
PRINT N'Dropping CREATE_TABLE events from DatabaseLog table...'
DELETE FROM [dbo].[DatabaseLog] WHERE Event = N'CREATE_TABLE'
PRINT N'Dropping ALTER_TABLE events from DatabaseLog table...'
DELETE FROM [dbo].[DatabaseLog] WHERE Event = N'ALTER_TABLE'
PRINT N'Done!'
当来自 SSMS 运行 时,针对 AdventureWorks 2012,它给出了这个输出:
Dropping CREATE_TABLE events from DatabaseLog table...
(70 row(s) affected)
Dropping ALTER_TABLE events from DatabaseLog table...
(117 row(s) affected)
Done!
如何在 .NET 中重现这一点,包括受影响的行?
通过挂接到 SqlConnection
上的 InfoMessage
事件,我得到了 PRINT
语句的输出,但这不包括受影响行的行。理想情况下,我想像 SSMS 中的 运行 一样捕获输出。
注意:脚本是用户提供的,因此修改脚本以手动输出行计数不是一种选择。
ExecuteNonQuery
应该 return 受影响的行;
SqlCommand comm = new SqlCommand("DELETE FROM [dbo].[DatabaseLog] WHERE Event = N'CREATE_TABLE'",conn);
int rowsAffected = comm.ExecuteNonQuery();
终于找到了正确的事件来获取单个语句的计数! StatementCompleted
对单个 SqlCommand
触发多次,每个影响行的语句触发一次。所以:
public static void ExecuteScript(string connectionString, string sql)
{
using (var conn = new SqlConnection(connectionString))
{
conn.InfoMessage += (sender, args) => Console.WriteLine(args.Message);
conn.FireInfoMessageEventOnUserErrors = true;
conn.Open();
using (var cmd = new SqlCommand(sql, conn))
{
cmd.StatementCompleted += (sender, args) =>
Console.WriteLine($"{Environment.NewLine}({args.RecordCount} row(s) affected)");
cmd.ExecuteNonQuery();
}
}
}
重现 SSMS 的输出,针对我迄今为止尝试过的查询,其中包括 CREATE TABLE
、PRINT
、INSERT
、DELETE
和 SELECT
.
必须将 FireInfoMessageEventOnUserErrors
设置为 true
,否则所有 InfoMessage
事件都会出现在末尾,而不是与 StatementCompleted
事件正确交错。但是,当FireInfoMessageEventOnUserErrors
设置为true
时,如果有错误则不会抛出SqlException
,所以必须检查每个InfoMessage是否有错误(如果Class
设置为> 10).
考虑这个简单的 SQL 脚本:
PRINT N'Dropping CREATE_TABLE events from DatabaseLog table...'
DELETE FROM [dbo].[DatabaseLog] WHERE Event = N'CREATE_TABLE'
PRINT N'Dropping ALTER_TABLE events from DatabaseLog table...'
DELETE FROM [dbo].[DatabaseLog] WHERE Event = N'ALTER_TABLE'
PRINT N'Done!'
当来自 SSMS 运行 时,针对 AdventureWorks 2012,它给出了这个输出:
Dropping CREATE_TABLE events from DatabaseLog table...
(70 row(s) affected)
Dropping ALTER_TABLE events from DatabaseLog table...
(117 row(s) affected)
Done!
如何在 .NET 中重现这一点,包括受影响的行?
通过挂接到 SqlConnection
上的 InfoMessage
事件,我得到了 PRINT
语句的输出,但这不包括受影响行的行。理想情况下,我想像 SSMS 中的 运行 一样捕获输出。
注意:脚本是用户提供的,因此修改脚本以手动输出行计数不是一种选择。
ExecuteNonQuery
应该 return 受影响的行;
SqlCommand comm = new SqlCommand("DELETE FROM [dbo].[DatabaseLog] WHERE Event = N'CREATE_TABLE'",conn);
int rowsAffected = comm.ExecuteNonQuery();
终于找到了正确的事件来获取单个语句的计数! StatementCompleted
对单个 SqlCommand
触发多次,每个影响行的语句触发一次。所以:
public static void ExecuteScript(string connectionString, string sql)
{
using (var conn = new SqlConnection(connectionString))
{
conn.InfoMessage += (sender, args) => Console.WriteLine(args.Message);
conn.FireInfoMessageEventOnUserErrors = true;
conn.Open();
using (var cmd = new SqlCommand(sql, conn))
{
cmd.StatementCompleted += (sender, args) =>
Console.WriteLine($"{Environment.NewLine}({args.RecordCount} row(s) affected)");
cmd.ExecuteNonQuery();
}
}
}
重现 SSMS 的输出,针对我迄今为止尝试过的查询,其中包括 CREATE TABLE
、PRINT
、INSERT
、DELETE
和 SELECT
.
必须将 FireInfoMessageEventOnUserErrors
设置为 true
,否则所有 InfoMessage
事件都会出现在末尾,而不是与 StatementCompleted
事件正确交错。但是,当FireInfoMessageEventOnUserErrors
设置为true
时,如果有错误则不会抛出SqlException
,所以必须检查每个InfoMessage是否有错误(如果Class
设置为> 10).