Search code examples
servicestacksqldatareaderormlite-servicestack

Servicestack OrmLite: Capture PRINT statements from stored procedure


I'm currently writing a console app that kicks off a number of stored procedures in our (Sql Server) database. The app is primarily responsible for executing the procedures, logging events to a number of places, and then some arbitrary work after. We have a nice Data NuGet package out there that integrates with OrmLite / ServiceStack, so I'm trying to use OrmLite as our ORM here as well.

The app itself just takes inputs that include the name of the sproc, and I'm executing them based off that (string) name. The sprocs themselves just move data; the app doesn't need to know the database model (and can't; the models can change).

Since these sprocs do quite a bit of work, the sprocs themselves output logging via PRINT statements. It's my goal to include these PRINTed log messages in the logging of the console app.

Is it possible to capture PRINT messages from a DbConnection command? I can't find any way via the built-in commands to capture this; only errors. Do I have to use ExecuteReader() to get a hold of the DataReader and read them that way?

Any help is appreciated. Thanks!


Solution

  • Enable Debug Logging

    If you configure ServiceStack with a debug enabled logger it will log the generated SQL + params to the configured logger.

    So you could use the StringBuilderLogFactory to capture the debug logging into a string.

    CaptureSqlFilter

    OrmLite does have a feature where you can capture the SQL output of a command using the CaptureSqlFilter:

    using (var captured = new CaptureSqlFilter())
    using (var db = OpenDbConnection())
    {
        db.Where<Person>(new { Age = 27 });
    
        captured.SqlStatements[0].PrintDump();
    }
    

    But this doesn't execute the statement, it only captures it.

    Custom Exec Filter

    You could potentially use a Custom Exec Filter to execute the command and call a custom function with:

    public class CaptureOrmLiteExecFilter : OrmLiteExecFilter
    {
        public override T Exec<T>(IDbConnection dbConn, Func<IDbCommand, T> filter)
        {
            var holdProvider = OrmLiteConfig.DialectProvider;
            var dbCmd = CreateCommand(dbConn);
            try
            {
                return filter(dbCmd);
            }
            finally
            {
                MyLog(dbCmd);
                DisposeCommand(dbCmd);
                OrmLiteConfig.DialectProvider = holdProvider;
            }
        }
    }
    
    //Configure OrmLite to use above Exec filter
    OrmLiteConfig.ExecFilter = new CaptureOrmLiteExecFilter();