背景:我们正在使用 AdoNetAppender 登录 Oracle 数据库。有 5 个单元测试,所有这些单元测试都将虚拟错误消息记录到同一个表中。Logger 实例由 Unity 解析,生命周期为 PerThreadLifetimeManager。
登录数据库的代码如下
public void Error(LogInformation message, Exception exception)
{
mapLogInformationToContext(message);
Task.Factory.StartNew(() => Logger.Log(_stackBoundary, Level.Error, message, exception));
}`
并将日志信息映射到ThreadContext,如下图:
private static void mapLogInformationToContext(LogInformation message)
{
ThreadContext.Properties["LogUserName"] = message.LogUserName;
ThreadContext.Properties["LogMachineName"] = message.LogMachineName;
ThreadContext.Properties["LogType"] = message.LogType;
ThreadContext.Properties["LogCreateDate"] = message.LogCreateDate == default(DateTime) ? DateTime.Now : message.LogCreateDate;
if (message.LogPropertiesXml != null)
{
ThreadContext.Properties["LogPropertiesXml"] = message.LogPropertiesXml.Trim();
}
}
我们面临的问题是 LogPropertiesXml。即使是格式良好的 Xml 也无法使用 Task.Factory.StartNew 登录到数据库。如果消除了 Tasking,则所有 5 个单元测试都可以工作。否则只有 1-2 个测试随机登录到数据库,其他测试失败并出现此错误
ORA-19202:XML 处理 LPX-00210 中发生错误:预期 '<' 而不是 '(' 在 Oracle.DataAccess.Client.OracleException.HandleErrorHelper(Int32 errCode, OracleConnection conn, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Oracle.DataAccess.Client.OracleException.HandleError(Int32 errCode, OracleConnection conn, String procedure, IntPtr opsErrCtx, OpoSqlValCtx* pOpoSqlValCtx, Object src, Boolean bCheck) 在 Oracle.DataAccess 的 Object src, String procedure, Boolean bCheck, Int32 isRecoverable)。 Client.OracleCommand.ExecuteNonQuery() 在 log4net.Appender.AdoNetAppender.SendBuffer(IDbTransaction dbTran, LoggingEvent[] events) 在 log4net.Appender.AdoNetAppender.SendBuffer(LoggingEvent[] events)
我在这里做错了什么?