我使用Log4Net Windows服务将日志保存在数据库中。我收到以下错误:
log4net:ERROR [CustomAdoNetAppender] ErrorCode: GenericFailure. Failed in DoAppend
System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding. ---> System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
at System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
at System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
at System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
at System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value)
at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName, Boolean shouldReconnect)
at System.Data.SqlClient.SqlConnection.BeginTransaction(IsolationLevel iso, String transactionName)
at System.Data.SqlClient.SqlConnection.BeginDbTransaction(IsolationLevel isolationLevel)
at System.Data.Common.DbConnection.System.Data.IDbConnection.BeginTransaction()
at log4net.Appender.AdoNetAppender.SendBuffer(LoggingEvent[] events)
at log4net.Appender.BufferingAppenderSkeleton.Append(LoggingEvent loggingEvent)
at log4net.Appender.AppenderSkeleton.DoAppend(LoggingEvent loggingEvent)
ClientConnectionId:a0b7de5e-2689-407b-b0da-5ebc733c0986
log4net: Attempting to reconnect to database. Current Connection State: Closed
log4net: Attempting to reconnect to database. Current Connection State: (null)
log4net: Attempting to reconnect to database. Current Connection State: (null)
log4net: Attempting to reconnect to database. Current Connection State: (null)
log4net: Attempting to reconnect to database. Current Connection State: (null)
我在服务窗口中的配置 Lo4Net 是:
<log4net>
<appender name="AdoNetAppender" type="App.Uteis.CustomAdoNetAppender">
<bufferSize value="1" />
<reconnectonerror value="true" />
<connectionType value="System.Data.SqlClient.SqlConnection, System.Data, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<commandText value="INSERT INTO Log_Aplicacao ([Dt_Log],[Ds_Thread],[Ds_Nivel],[Ds_Servidor],[Ds_Aplicacao],[Ds_Login],[Ds_Log],[Ds_Mensagem],[Ds_Erro]) VALUES (@log_date, @thread, @log_level, @host_name,'AppMaster', @user_name, @logger, @message, @exception)" />
<parameter>
<parameterName value="@log_date" />
<dbType value="DateTime" />
<layout type="log4net.Layout.RawTimeStampLayout" />
</parameter>
<parameter>
<parameterName value="@thread" />
<dbType value="String" />
<size value="255" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%thread" />
</layout>
</parameter>
<parameter>
<parameterName value="@log_level" />
<dbType value="String" />
<size value="50" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%level" />
</layout>
</parameter>
<parameter>
<parameterName value="@host_name" />
<dbType value="String" />
<size value="200" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%property{log4net:HostName}" />
</layout>
</parameter>
<parameter>
<parameterName value="@user_name" />
<dbType value="String" />
<size value="150" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%username" />
</layout>
</parameter>
<parameter>
<parameterName value="@logger" />
<dbType value="String" />
<size value="2000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%logger" />
</layout>
</parameter>
<parameter>
<parameterName value="@message" />
<dbType value="String" />
<size value="8000" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%message" />
</layout>
</parameter>
<parameter>
<parameterName value="@exception" />
<dbType value="String" />
<size value="8000" />
<layout type="log4net.Layout.ExceptionLayout" />
</parameter>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="AdoNetAppender" />
</root>
</log4net>
我的 CustomAdoNetAppender 类的配置是:
namespace AprovadorCartao.Uteis
{
public class CustomAdoNetAppender : AdoNetAppender
{
public static RegistryKey _configRegistry = Registry.LocalMachine.OpenSubKey("Software\Conexao");
public override void ActivateOptions()
{
PopulateConnectionString();
base.ActivateOptions();
}
private void PopulateConnectionString()
{
ConnectionString = ConnectionString;
}
public new string ConnectionString
{
get { return base.ConnectionString; }
set
{
base.ConnectionString = (string)_configRegistry.GetValue("Conexao") + ";Connect Timeout=1;";
}
}
}
}
Log4Net 只有在重新启动服务后才能恢复正常(保存在数据库中)。
每当我的数据库出现错误时,Log4Net都会将数据保存在数据库中。是否有任何配置可以让 Log4Net 再次自动登录 Windows 服务?
由于您已经设置了reconnectOnError = true
并且您正在使用适当低的连接超时,因此您走在正确的轨道上 - 我认为这里的问题是您没有通过设置正确覆盖连接字符串,您应该覆盖ResolveConnectionString()
以替换超时值:
protected override string ResolveConnectionString(out string connectionStringContext)
{
var connectionString = base.ResolveConnectionString(out connectionStringContext);
if (string.IsNullOrEmpty(connectionString) || ReconnectOnError == false)
{
return connectionString;
}
var builder = new SqlConnectionStringBuilder(connectionString)
{
ConnectTimeout = 1; // Timeout value
};
return builder.ConnectionString;
}