VB.NET项目中log4net动态初始化连接字符串失败求助
在VB.NET项目的startup.vb文件中,我尝试为log4net动态初始化连接字符串(初始化前已完成log4net配置),代码如下:
Dim rep As log4net.Repository.ILoggerRepository = log4net.LogManager.GetRepository() If rep Is Nothing Then Throw New InvalidOperationException("Unable to get log4net Repository.") Else For Each adoNetAppender As log4net.Appender.AdoNetAppender In rep.GetAppenders().OfType(Of log4net.Appender.AdoNetAppender)() adoNetAppender.ConnectionString = DataAccess.GetConnectionString(DataAccess.DBInstance.ICPS) adoNetAppender.ActivateOptions() Next End If
Appender已获取到当前运行环境对应的正确数据库实例凭据,但运行应用时抛出以下错误,日志无法插入目标表:
log4net:ERROR [AdoNetAppender] ErrorCode: GenericFailure. Could not open database connection []. Connection string context [Unable to resolve connection string from ConnectionString, ConnectionStrings, or AppSettings.].
System.InvalidOperationException: The ConnectionString property has not been initialized.
at System.Data.OracleClient.OracleConnection.PermissionDemand()
at System.Data.OracleClient.OracleConnectionFactory.PermissionDemand(DbConnection outerConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
at System.Data.OracleClient.OracleConnection.Open()
at log4net.Appender.AdoNetAppender.InitializeDatabaseConnection()
但在log4net.config文件的connectionString标签中配置相同的数据库凭据时,日志可正常插入表中。我的log4net.config配置如下:
<?xml version="1.0" encoding="utf-8" ?> <log4net> <appender name="ADONetAppender" type="log4net.Appender.AdoNetAppender"> <threshold value="ERROR" /> <bufferSize value="1" /> <connectionType value="System.Data.OracleClient.OracleConnection, System.Data.OracleClient, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> <!--<connectionString value="Data Source=ICD3.WORLD; User Id=icpsuser; Password=icpsusr; Persist Security Info=True; Pooling=true; Min Pool Size=1; Max Pool Size=50"/> --> <!-- Connection string is dynamically defined inside startup.vb--> <commandText value="INSERT INTO ICPSOWNER.DEBUG_LOG (SEQ_NBR, INSERT_DATE, ACTIVITY, ACTIVITY_DETAIL) VALUES (DEBUG_LOG_SEQ.NextVal, sysdate, :Log_Method, :Log_Message)" /> <parameter> <parameterName value=":Log_Method" /> <dbType value="String" /> <size value="50" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%method" /> </layout> </parameter> <parameter> <parameterName value=":Log_Message" /> <dbType value="String" /> <size value="1000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%message" /> </layout> </parameter> </appender> <root> <level value="ERROR" /> <appender-ref ref="ADONetAppender" /> </root> </log4net>
请问遗漏了什么配置或步骤?为何相同数据库凭据下,动态初始化连接字符串失效,而显式配置却能正常工作?
核心原因
log4net的AdoNetAppender初始化时,如果配置文件中完全没有connectionString节点,会默认尝试从ConnectionStrings配置节或AppSettings中读取连接字符串,不会直接识别代码设置的ConnectionString属性。就算后续通过代码赋值,Appender内部的连接初始化逻辑要么已提前触发,要么未正确加载手动设置的值。另外,如果代码执行晚于首次日志写入操作,也会导致设置失效。
解决步骤
配置文件保留空的
connectionString节点
不要完全注释掉connectionString标签,保留一个空节点,让log4net明确使用手动设置的连接字符串,而非自动查找配置:<connectionString value="" />提前代码执行时机
确保这段动态设置代码在项目启动最早期执行——比如Web项目的Application_Start方法开头、桌面项目的Main方法开头,必须在任何日志记录操作之前完成初始化。强制重置Appender连接(可选)
如果上述步骤仍有问题,可以先关闭Appender再重新激活,确保连接状态被覆盖:For Each adoNetAppender As log4net.Appender.AdoNetAppender In rep.GetAppenders().OfType(Of log4net.Appender.AdoNetAppender)() adoNetAppender.Close() ' 关闭现有连接 adoNetAppender.ConnectionString = DataAccess.GetConnectionString(DataAccess.DBInstance.ICPS) adoNetAppender.ActivateOptions() ' 重新加载配置 Next
显式配置正常工作的原因
当配置文件中有完整的connectionString节点时,log4net会直接用该值初始化Appender的连接属性,跳过自动查找逻辑,因此能正常建立连接写入日志。而动态设置时,因配置文件无此节点,Appender走了自动查找分支,导致无法识别手动设置的连接字符串。
内容的提问来源于stack exchange,提问作者Ramya B S

