简体   繁体   中英

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.

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.

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. 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.

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. 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 )?

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.

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 = dbCmd => Console.WriteLine(dbCmd.GetDebugString());

This change is available from v5.0.3 that's now available on MyGet .

Update:

Looking through the ServiceStack.OrmLite source, it looks like IDbConnection can be cast to SqlConnection using (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:

 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. Just thought I'd plop this here in case it suits anyone's use case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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