很难相信,但我似乎无法找到一个直接的答案:当语句生成异常时,如何获取SQL语句包括参数值并且只有在它产生异常时。我知道如何为每个生成的SQL记录语句+参数,但这太过分了。但是,当有System.Data.SqlClient.SqlException
时,它只提供SQL,而不是参数值。如何在我可以访问该数据的位置捕获它,以便我可以记录它?
答案 0 :(得分:2)
根据对各种问题(不仅仅是我的)的一些回答,我拼凑了一些可以解决这个问题的问题。我认为它也可能对其他人有用,所以我在这里包括很多内容:
基本想法是
我使用Log4Net,设置如下:
<?xml version="1.0"?>
<log4net>
<appender name="RockAndRoll" type="Util.PrettySqlRollingFileAppender, Util">
<file type="log4net.Util.PatternString" >
<conversionPattern value="%env{Temp}\\%property{LogDir}\\MyApp.log" />
</file>
<DatePattern value="MM-dd-yyyy" />
<appendToFile value="true" />
<immediateFlush value="true" />
<rollingStyle value="Composite" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="100MB" />
<staticLogFileName value="true" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date %-5level %logger - %message%newline" />
</layout>
</appender>
<appender name="ErrorBufferingAppender" type="log4net.Appender.BufferingForwardingAppender">
<bufferSize value="2" />
<lossy value="true" />
<evaluator type="log4net.Core.LevelEvaluator">
<threshold value="ERROR" />
</evaluator>
<appender-ref ref="RockAndRoll" />
<Fix value="0" />
</appender>
<logger name="NHibernate.SQL">
<additivity>false</additivity>
<appender-ref ref="ErrorBufferingAppender" />
<level value="debug" />
</logger>
<logger name="error-buffer">
<additivity>false</additivity>
<appender-ref ref="ErrorBufferingAppender" />
<level value="debug" />
</logger>
<root>
<level value="info" />
<appender-ref ref="RockAndRoll" />
</root>
</log4net>
NHibernate.SQL
记录器将所有查询记录到ErrorBufferingAppender
,这会将它们抛出并仅将最后一个保存在其缓冲区中。当我捕获异常时,我将ERROR级别的一行记录到记录器error-buffer
,将其传递给ErrorBufferingAppender
,因为它处于ERROR级别 - 将其与最后一个查询一起推送到RockAndRoll
,RollingFileAppender
。
我实现了一个名为RollingFileAppender
的{{1}}的子类(我很乐意提供,如果有人感兴趣的话)从查询结尾获取参数并将它们替换为查询本身,它更具可读性。
答案 1 :(得分:0)
如果您使用nhibernate查询数据库(因为您的问题中的标记存在建议),并且您的SQL方言/驱动程序依赖于ADO,那么您应该从失败的查询中获取GenericADOException
其Message
属性通常已包含参数值。
例如,执行以下失败的查询(假设您在DB中至少有一行):
var result = session.Query<Entity>()
.Where(e => e.Name.Length / 0 == 1);
产生GenericADOException
消息:
could not execute query
[ select entity0_.Id as Id1_0_, entity0_.Name as Name2_0_ from Entity entity0_ where len(entity0_.Name)/@p0=@p1 ]
Name:p1 - Value:0 Name:p2 - Value:1
查询的两个文字0
和1
已经过参数化,它们的值包含在消息中(索引库不匹配:在hibernate查询中,它们是{{1}基于我的设置的SQL查询,它们最终基于1
。
因此,拥有它们没有什么特别之处。只需记录异常消息。
你是否错过了它,或者你确实在问别的什么? 在我看来,你的问题不够明确。您应该包含MVCE。它会更准确地告诉我在这种情况下你无法获得这些参数值。