ServiceStack OrmLite - 从存储过程捕获 Sql InfoMessage 事件
ServiceStack OrmLite - Capture Sql InfoMessage event from stored procedure
几天前问过这个问题,但可能不太具体。
基本上,我正在编写一个控制台应用程序,它接受存储过程名称列表并任意执行它们。该应用程序应该将这些存储过程的进度记录到 Slack 等,以及稍后做一些其他事情。
我提到的 'other stuff' 与已知的数据库模型交互,并且由于我们建立了一个 ServiceStack/OrmLite 类型的库,我稍后将使用 OrmLite 与数据库交互。
因此,由于我在项目中包含并配置了 OrmLite,我只是使用 OrmLite IDbConnection
来执行存储过程,即使它只是按名称。 sprocs 只是将数据移动到另一个数据库,应用程序不需要与之交互的数据库 - 所以我没有 SELECT
使用 sprocs 将任何数据输入到应用程序中,并且没有移动内容的 POCO 表示。
然而,sprocs 吐出一些信息性的 PRINT
语句,我想通过 Slack 以格式化的方式捕获并记录到我们的团队。为此,启用完整的调试日志记录会吐出太多信息。
有什么方法可以配置 Ormlite
SqlServerDialect.Provider
、IDataReader
等以基本捕获 SqlConnection.InfoMessage
事件(或为它提供一个已经准备好 SqlInfoMessageEventHandler
的连接)?
执行此操作的日志记录策略方法是在您的日志记录提供程序中配置一个过滤器,以仅记录您感兴趣的消息。
OrmLite 的 SQL 包含 SQL 和数据库参数的调试日志记录消息记录在 ServiceStack.OrmLite.OrmLiteResultsFilterExtensions
类型下。
为了简化此场景,我刚刚添加了新的 OrmLiteConfig.BeforeExecFilter
和 OrmLiteConfig.AfterExecFilter
,您可以使用它们在执行数据库命令之前和之后执行自定义逻辑,例如:
OrmLiteConfig.BeforeExecFilter = dbCmd => Console.WriteLine(dbCmd.GetDebugString());
此更改适用于现在 available on MyGet 的 v5.0.3。
更新:
查看 ServiceStack.OrmLite 源代码,看起来 IDbConnection
可以使用 (SqlConnection)IDbConnection.ToDbConnetion()
.
转换为 SqlConnection
将其包装在 OrmLiteExecFilter
中以在每个语句中调用,转换 IDbConnection
并使用转换连接创建 DbCommand
对我有用:
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();
但是,既然@mythz 已经回复了 'official' 方法来做到这一点,我将着手进行重构。只是想我会把它放在这里以防它适合任何人的用例。
几天前问过这个问题,但可能不太具体。
基本上,我正在编写一个控制台应用程序,它接受存储过程名称列表并任意执行它们。该应用程序应该将这些存储过程的进度记录到 Slack 等,以及稍后做一些其他事情。
我提到的 'other stuff' 与已知的数据库模型交互,并且由于我们建立了一个 ServiceStack/OrmLite 类型的库,我稍后将使用 OrmLite 与数据库交互。
因此,由于我在项目中包含并配置了 OrmLite,我只是使用 OrmLite IDbConnection
来执行存储过程,即使它只是按名称。 sprocs 只是将数据移动到另一个数据库,应用程序不需要与之交互的数据库 - 所以我没有 SELECT
使用 sprocs 将任何数据输入到应用程序中,并且没有移动内容的 POCO 表示。
然而,sprocs 吐出一些信息性的 PRINT
语句,我想通过 Slack 以格式化的方式捕获并记录到我们的团队。为此,启用完整的调试日志记录会吐出太多信息。
有什么方法可以配置 Ormlite
SqlServerDialect.Provider
、IDataReader
等以基本捕获 SqlConnection.InfoMessage
事件(或为它提供一个已经准备好 SqlInfoMessageEventHandler
的连接)?
执行此操作的日志记录策略方法是在您的日志记录提供程序中配置一个过滤器,以仅记录您感兴趣的消息。
OrmLite 的 SQL 包含 SQL 和数据库参数的调试日志记录消息记录在 ServiceStack.OrmLite.OrmLiteResultsFilterExtensions
类型下。
为了简化此场景,我刚刚添加了新的 OrmLiteConfig.BeforeExecFilter
和 OrmLiteConfig.AfterExecFilter
,您可以使用它们在执行数据库命令之前和之后执行自定义逻辑,例如:
OrmLiteConfig.BeforeExecFilter = dbCmd => Console.WriteLine(dbCmd.GetDebugString());
此更改适用于现在 available on MyGet 的 v5.0.3。
查看 ServiceStack.OrmLite 源代码,看起来 IDbConnection
可以使用 (SqlConnection)IDbConnection.ToDbConnetion()
.
SqlConnection
将其包装在 OrmLiteExecFilter
中以在每个语句中调用,转换 IDbConnection
并使用转换连接创建 DbCommand
对我有用:
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();
但是,既然@mythz 已经回复了 'official' 方法来做到这一点,我将着手进行重构。只是想我会把它放在这里以防它适合任何人的用例。