简体   繁体   English

ServiceStack OrmLite - 从存储过程捕获Sql InfoMessage事件

[英]ServiceStack OrmLite - Capture Sql InfoMessage event from stored procedure

Asked this question a few days ago but maybe wasn't too specific. 几天前问过这个问题,但也许并不太具体。

Basically, I'm writing a console app that accepts a list of stored procedure names and arbitrarily executes them. 基本上,我正在编写一个控制台应用程序,它接受存储过程名称列表并随意执行它们。 The app is supposed to log to Slack, etc. on the progress of these sprocs, as well as do some other stuff later. 应用程序应该记录Slack等关于这些sprocs的进展,以及稍后做一些其他的事情。

The 'other stuff' I mentioned interacts with known database models, and since we have a library of ServiceStack/OrmLite types build up, I am using OrmLite to interact with the database later. 我提到的“其他东西”与已知的数据库模型交互,因为我们有一个ServiceStack / OrmLite类型库,所以我以后使用OrmLite与数据库进行交互。

So, since I have OrmLite included and configured in the project, I'm just using the OrmLite IDbConnection to execute the stored procedures, even if it's just by name. 因此,由于我在项目中包含并配置了OrmLite,我只是使用OrmLite IDbConnection来执行存储过程,即使它只是名称。 The sprocs simply move data to another database, one that the app doesn't need to interact with -- so I'm not SELECT ing any data into the app with the sprocs and there's no POCO representation of what's moved. sprocs只是将数据移动到另一个数据库,一个应用程序不需要与之交互的数据库 - 因此我不会使用sprocs将任何数据SELECT到应用程序中,并且没有POCO表示移动的内容。

However, the sprocs spit out a number of informational PRINT statements that I want to capture and log to our team in a formatted manner via Slack. 然而,sprocs吐出了许多我想捕获的信息PRINT语句,并通过Slack以格式化方式登录我们的团队。 Enabling full-on debug logging spits out a little too much information for this purpose. 启用完整的调试日志记录会为此目的提供一些过多的信息。

Is there any way I can configure the Ormlite SqlServerDialect.Provider , the IDataReader , etc. to basically capture the SqlConnection.InfoMessage event (or to provide it with a connection already prepped with a SqlInfoMessageEventHandler )? 有没有什么方法可以配置Ormlite SqlServerDialect.ProviderIDataReader等基本上捕获SqlConnection.InfoMessage事件(或者为它提供已经准备好SqlInfoMessageEventHandler的连接)?

The logging strategy approach for doing this is to configure a filter in your logging provider to only log the messages you're interested in. 执行此操作的日志记录策略方法是在日志记录提供程序中配置过滤器,以仅记录您感兴趣的消息。

OrmLite's SQL debug logging messages containing the SQL and DB Params are logged under the ServiceStack.OrmLite.OrmLiteResultsFilterExtensions Type. 包含SQL和DB参数的OrmLite的SQL调试日志消息记录在ServiceStack.OrmLite.OrmLiteResultsFilterExtensions类型下。

To make this scenario easier I've just added new OrmLiteConfig.BeforeExecFilter and OrmLiteConfig.AfterExecFilter which you can use to execute custom logic before and after a DB Command is executed, eg: 为了OrmLiteConfig.BeforeExecFilter这个场景,我刚刚添加了新的OrmLiteConfig.BeforeExecFilterOrmLiteConfig.AfterExecFilter ,您可以在执行DB命令之前和之后执行自定义逻辑,例如:

OrmLiteConfig.BeforeExecFilter = dbCmd => Console.WriteLine(dbCmd.GetDebugString());

This change is available from v5.0.3 that's now available on MyGet . 此更改可从v5.0.3获得,现在可在MyGet上使用

Update: 更新:

Looking through the ServiceStack.OrmLite source, it looks like IDbConnection can be cast to SqlConnection using (SqlConnection)IDbConnection.ToDbConnetion() . 通过ServiceStack.OrmLite来源看,它看起来像IDbConnection可以转换为SqlConnection使用(SqlConnection)IDbConnection.ToDbConnetion()

Wrapping this up in an OrmLiteExecFilter to be called on every statement, casting the IDbConnection and creating the DbCommand with the cast connection worked for me: 将其包装在OrmLiteExecFilter以在每个语句上调用,转换IDbConnection并使用强制转换连接创建DbCommand对我OrmLiteExecFilter

 public class LogInfoMessageFilter : OrmLiteExecFilter { ILog SlackLog = LogManager.GetLogger("SlackLogger"); public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter) { var holdProvider = OrmLiteConfig.DialectProvider; // casting, skipping type checks for brevity var sqlConn = (SqlConnection)dbConn.ToDbConnection(); // add the event sqlConn.InfoMessage += _HandleInfoMessage; var dbCmd = CreateCommand(sqlConn); try { return filter(dbCmd); } finally { DisposeCommand(dbCmd, sqlConn); OrmLiteConfig.DialectProvider = holdProvider; } } private void _HandleInfoMessage(object sender, SqlInfoMessageEventArgs args) { SlackLog.Info($"what does the sproc say? {args.Message}"); } } // before opening the connection: OrmLiteConfig.ExecFilter = new LogInfoMessageFilter(); 

However, now that @mythz has replied with an 'official' way to do this, I'll go about refactoring. 但是,现在@mythz用“官方”方式回复了这个问题,我将继续进行重构。 Just thought I'd plop this here in case it suits anyone's use case. 我以为我会把它放在这里,以防它适合任何人的用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM