Servicestack OrmLite:如何捕获SQL Server存储过程的PRINT语句
捕获SQL Server存储过程PRINT输出的OrmLite实现方案
我之前在基于OrmLite/ServiceStack的项目里处理过完全一样的需求——捕获存储过程的PRINT语句输出,其实核心是利用ADO.NET底层的事件机制,因为OrmLite本质上是对ADO.NET的轻量封装,咱们可以直接拿到底层的SqlConnection来订阅消息事件。
下面是具体的实现步骤和代码示例:
1. 准备消息存储容器
首先需要一个线程安全的集合来存放捕获到的PRINT消息(因为InfoMessage事件可能异步触发,控制台应用里用ConcurrentBag就很合适):
using System.Collections.Concurrent; private static readonly ConcurrentBag<string> _capturedPrintMessages = new ConcurrentBag<string>();
2. 订阅SqlConnection的InfoMessage事件
在打开OrmLite数据库连接后,获取底层的SqlConnection,并订阅它的InfoMessage事件——这个事件专门用来接收SQL Server的PRINT输出以及低严重度(severity < 11)的RAISERROR消息:
using (var db = dbFactory.Open()) { // 获取底层的SqlConnection实例 var sqlConnection = db.UnderlyingConnection as SqlConnection; if (sqlConnection != null) { sqlConnection.InfoMessage += (sender, eventArgs) => { // 遍历所有捕获到的消息(PRINT的内容会在这里) foreach (var sqlError in eventArgs.Errors) { var printMessage = sqlError.Message; _capturedPrintMessages.Add(printMessage); // 这里可以直接写入你的日志系统,或者实时输出到控制台 Console.WriteLine($"存储过程PRINT输出: {printMessage}"); } }; } // 调用你的存储过程,用OrmLite的SqlProc方法即可 var procedureResult = db.SqlProc("YourTargetStoredProcedure", new { Param1 = "yourParamValue", Param2 = 456 }); // 处理捕获到的消息,比如写入日志或执行自定义操作 foreach (var msg in _capturedPrintMessages) { // 替换成你的日志记录逻辑 Logger.LogInformation($"捕获到PRINT内容: {msg}"); } // 如果需要多次调用,记得清空容器避免消息混淆 _capturedPrintMessages.Clear(); }
3. 关键注意事项
- 驱动版本:确保你引用的是
System.Data.SqlClient或者Microsoft.Data.SqlClient(根据你的SQL Server版本选择,后者是微软推荐的新版驱动); - 事件订阅时机:务必在执行存储过程之前订阅
InfoMessage事件,否则可能会错过消息; - 消息过滤:如果只想捕获PRINT输出而排除RAISERROR,可以在事件处理里加判断——PRINT的消息通常severity为0,你可以通过
sqlError.Class来筛选(sqlError.Class == 0); - OrmLite兼容性:这个方法完全兼容ServiceStack OrmLite的各种版本,不会破坏你现有的Data NuGet包集成逻辑。
这种方案既利用了OrmLite的便捷性,又通过底层ADO.NET的事件实现了PRINT输出的捕获,完美适配你的控制台应用场景。
内容的提问来源于stack exchange,提问作者joh04667
相关产品推荐
相关产品推荐

