Log4net 自定义字段 写入Oracle 使用ODP.NET Managed驱动
一、环境说明:
开发工具:vs2010 ,数据库:oracle 11g ,版本:log4net的目前最新版本1.2.13.0 ; Oracle.ManagedDataAccess.dll Version 4.121.1.0
二、官网dll准备
log4net http://mirrors.hust.edu.cn/apache//logging/log4net/binaries/log4net-1.2.13-bin-newkey.zip
Oracle.ManagedDataAccess.dll 官网 http://www.oracle.com/technetwork/topics/dotnet/downloads/index.html
三、实现步骤(以个人建立的项目为例子解说)
1、建立项目log4netTest5,把dll放在Lib文件内, 打开项目 引用 把dll 引入项目
2、建立log4net.config 配置文件(周公等网上的达人都详解的很清楚了,我就讲解oracle哪一部分)
注意: <appender name="AdoNetAppender_ORCL" type="log4net.Appender.OracleAppender">
数据驱动
<connectionType value="Oracle.ManagedDataAccess.Client.OracleConnection,Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />
数据库连接串
<connectionString value="Data Source=//localhost:1521/orcl;User ID=user;Password=user;" />
还有
<commandText value="insert into SECURITY_LOG4NET
按照自己的实际情况自己修改
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections> <log4net> <appender name="AdoNetAppender_ORCL" type="log4net.Appender.OracleAppender"> <bufferSize value="1"/> <connectionType value="Oracle.ManagedDataAccess.Client.OracleConnection,Oracle.ManagedDataAccess, Version=4.121.1.0, Culture=neutral, PublicKeyToken=89b483f429c47342" /> <connectionString value="Data Source=//localhost:1521/orcl;User ID=user;Password=user;" /> <commandText value="insert into SECURITY_LOG4NET (LOG_DATE,LOG_LEVEL,LOG_MESSAGE,LOG_EXCEPTION,LOG_LOGGER,LOG_SOURCE,USERID,LOGTYPE) VALUES (:log_date, :log_level,:log_message, :log_exception, :logger, :source,:USERID,:LOGTYPE)"/> <parameter> <parameterName value=":log_date" /> <dbType value="DateTime" /> <layout type="log4net.Layout.RawTimeStampLayout"> <conversionPattern value="%d{yyyy/MM/dd HH:mm:ss}" /> </layout> </parameter> <parameter> <parameterName value=":log_level" /> <dbType value="String" /> <size value="10" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%level" /> </layout> </parameter> <parameter> <parameterName value=":log_message" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%m" /> </layout> </parameter> <parameter> <parameterName value=":log_exception" /> <dbType value="String" /> <size value="4000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%exception" /> </layout> </parameter> <parameter> <parameterName value=":logger" /> <dbType value="String" /> <size value="255" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%logger" /> </layout> </parameter> <parameter> <parameterName value=":source" /> <dbType value="String" /> <size value="1000" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%file:%line" /> </layout> </parameter> <parameter> <parameterName value=":USERID" /> <dbType value="String" /> <size value="100" /> <layout type="Log4NetToDatabase.CustomLayout"> <conversionPattern value="%USERID" /> </layout> </parameter> <parameter> <parameterName value=":LOGTYPE" /> <dbType value="String" /> <size value="100" /> <layout type="Log4NetToDatabase.CustomLayout"> <conversionPattern value="%LOGTYPE" /> </layout> </parameter> </appender> <root> <level value ="ALL"/> <appender-ref ref="AdoNetAppender_ORCL"/> </root> </log4net> </configuration>
3、自己实现 OracleAppender.cs 和OracleAppenderParameter.cs
(我直接取自http://www.cnblogs.com/hnsongbiao/p/4216147.html#commentform)
1 public class OracleAppender : BufferingAppenderSkeleton 2 { 3 // Fields 4 private static readonly Type declaringType = typeof(AdoNetAppender); 5 private string m_commandText; 6 private CommandType m_commandType = CommandType.Text; 7 private string m_connectionString; 8 private string m_connectionType; 9 private OracleCommand m_dbCommand; 10 private OracleConnection m_dbConnection; 11 protected ArrayList m_parameters = new ArrayList(); 12 private bool m_reconnectOnError = false; 13 private SecurityContext m_securityContext; 14 protected bool m_usePreparedCommand; 15 private bool m_useTransactions = true; 16 17 // Methods 18 public override void ActivateOptions() 19 { 20 base.ActivateOptions(); 21 this.m_usePreparedCommand = (this.m_commandText != null) && (this.m_commandText.Length > 0); 22 if (this.m_securityContext == null) 23 { 24 this.m_securityContext = SecurityContextProvider.DefaultProvider.CreateSecurityContext(this); 25 } 26 this.InitializeDatabaseConnection(); 27 this.InitializeDatabaseCommand(); 28 } 29 30 public void AddParameter(OracleAppenderParameter parameter) 31 { 32 this.m_parameters.Add(parameter); 33 } 34 35 protected virtual string GetLogStatement(LoggingEvent logEvent) 36 { 37 if (this.Layout == null) 38 { 39 this.ErrorHandler.Error("ADOAppender: No Layout specified."); 40 return ""; 41 } 42 StringWriter writer = new StringWriter(CultureInfo.InvariantCulture); 43 this.Layout.Format(writer, logEvent); 44 return writer.ToString(); 45 } 46 47 private void InitializeDatabaseCommand() 48 { 49 if ((this.m_dbConnection != null) && this.m_usePreparedCommand) 50 { 51 try 52 { 53 this.m_dbCommand = this.m_dbConnection.CreateCommand(); 54 this.m_dbCommand.CommandText = this.m_commandText; 55 this.m_dbCommand.CommandType = this.m_commandType; 56 } 57 catch (Exception exception) 58 { 59 this.ErrorHandler.Error("Could not create database command [" + this.m_commandText + "]", exception); 60 if (this.m_dbCommand != null) 61 { 62 try 63 { 64 this.m_dbCommand.Dispose(); 65 } 66 catch 67 { 68 } 69 this.m_dbCommand = null; 70 } 71 } 72 if (this.m_dbCommand != null) 73 { 74 try 75 { 76 foreach (OracleAppenderParameter parameter in this.m_parameters) 77 { 78 try 79 { 80 parameter.Prepare(this.m_dbCommand); 81 } 82 catch (Exception exception2) 83 { 84 this.ErrorHandler.Error("Could not add database command parameter [" + parameter.ParameterName + "]", exception2); 85 throw; 86 } 87 } 88 } 89 catch 90 { 91 try 92 { 93 this.m_dbCommand.Dispose(); 94 } 95 catch 96 { 97 } 98 this.m_dbCommand = null; 99 } 100 } 101 if (this.m_dbCommand != null) 102 { 103 try 104 { 105 this.m_dbCommand.Prepare(); 106 } 107 catch (Exception exception3) 108 { 109 this.ErrorHandler.Error("Could not prepare database command [" + this.m_commandText + "]", exception3); 110 try 111 { 112 this.m_dbCommand.Dispose(); 113 } 114 catch 115 { 116 } 117 this.m_dbCommand = null; 118 } 119 } 120 } 121 } 122 123 private void InitializeDatabaseConnection() 124 { 125 try 126 { 127 this.m_dbConnection = new OracleConnection(); 128 this.m_dbConnection.ConnectionString = this.m_connectionString; 129 using (this.SecurityContext.Impersonate(this)) 130 { 131 this.m_dbConnection.Open(); 132 } 133 } 134 catch (Exception exception) 135 { 136 this.ErrorHandler.Error("Could not open database connection [" + this.m_connectionString + "]", exception); 137 this.m_dbConnection = null; 138 } 139 } 140 141 protected override void OnClose() 142 { 143 base.OnClose(); 144 if (this.m_dbCommand != null) 145 { 146 this.m_dbCommand.Dispose(); 147 this.m_dbCommand = null; 148 } 149 if (this.m_dbConnection != null) 150 { 151 this.m_dbConnection.Close(); 152 this.m_dbConnection = null; 153 } 154 } 155 156 protected virtual Type ResolveConnectionType() 157 { 158 Type type; 159 try 160 { 161 type = SystemInfo.GetTypeFromString(this.m_connectionType, true, false); 162 } 163 catch (Exception exception) 164 { 165 this.ErrorHandler.Error("Failed to load connection type [" + this.m_connectionType + "]", exception); 166 throw; 167 } 168 return type; 169 } 170 171 protected override void SendBuffer(LoggingEvent[] events) 172 { 173 if (this.m_reconnectOnError && ((this.m_dbConnection == null) || (this.m_dbConnection.State != ConnectionState.Open))) 174 { 175 LogLog.Debug(declaringType, "OracleAppender: Attempting to reconnect to database. Current Connection State: " + ((this.m_dbConnection == null) ? "<null>" : this.m_dbConnection.State.ToString())); 176 this.InitializeDatabaseConnection(); 177 this.InitializeDatabaseCommand(); 178 } 179 if ((this.m_dbConnection != null) && (this.m_dbConnection.State == ConnectionState.Open)) 180 { 181 if (this.m_useTransactions) 182 { 183 OracleTransaction dbTran = null; 184 try 185 { 186 dbTran = this.m_dbConnection.BeginTransaction(); 187 this.SendBuffer(dbTran, events); 188 dbTran.Commit(); 189 } 190 catch (Exception exception) 191 { 192 if (dbTran != null) 193 { 194 try 195 { 196 dbTran.Rollback(); 197 } 198 catch (Exception) 199 { 200 } 201 } 202 this.ErrorHandler.Error("Exception while writing to database", exception); 203 } 204 } 205 else 206 { 207 this.SendBuffer(null, events); 208 } 209 } 210 } 211 212 protected virtual void SendBuffer(OracleTransaction dbTran, LoggingEvent[] events) 213 { 214 if (!this.m_usePreparedCommand) 215 { 216 throw new NotImplementedException(); 217 } 218 if (this.m_dbCommand != null) 219 { 220 ArrayList list = null; 221 foreach (OracleAppenderParameter parameter in this.m_parameters) 222 { 223 list = new ArrayList(); 224 OracleParameter parameter2 = this.m_dbCommand.Parameters[parameter.ParameterName]; 225 foreach (LoggingEvent event2 in events) 226 { 227 object obj2 = parameter.Layout.Format(event2); 228 if (obj2.ToString() == "(null)") 229 { 230 obj2 = DBNull.Value; 231 } 232 list.Add(obj2); 233 } 234 parameter2.Value = list.ToArray(); 235 } 236 this.m_dbCommand.ArrayBindCount = events.Length; 237 this.m_dbCommand.ExecuteNonQuery(); 238 } 239 } 240 241 // Properties 242 public string CommandText 243 { 244 get 245 { 246 return this.m_commandText; 247 } 248 set 249 { 250 this.m_commandText = value; 251 } 252 } 253 254 public CommandType CommandType 255 { 256 get 257 { 258 return this.m_commandType; 259 } 260 set 261 { 262 this.m_commandType = value; 263 } 264 } 265 266 protected OracleConnection Connection 267 { 268 get 269 { 270 return this.m_dbConnection; 271 } 272 set 273 { 274 this.m_dbConnection = value; 275 } 276 } 277 278 public string ConnectionString 279 { 280 get 281 { 282 return this.m_connectionString; 283 } 284 set 285 { 286 this.m_connectionString = value; 287 } 288 } 289 290 public bool ReconnectOnError 291 { 292 get 293 { 294 return this.m_reconnectOnError; 295 } 296 set 297 { 298 this.m_reconnectOnError = value; 299 } 300 } 301 302 public SecurityContext SecurityContext 303 { 304 get 305 { 306 return this.m_securityContext; 307 } 308 set 309 { 310 this.m_securityContext = value; 311 } 312 } 313 314 public bool UseTransactions 315 { 316 get 317 { 318 return this.m_useTransactions; 319 } 320 set 321 { 322 this.m_useTransactions = value; 323 } 324 } 325 }
public class OracleAppenderParameter { // Fields private DbType m_dbType; private bool m_inferType = true; private IRawLayout m_layout; private string m_parameterName; private byte m_precision = 0; private byte m_scale = 0; private int m_size = 0; // Methods public virtual void FormatValue(OracleCommand command, LoggingEvent loggingEvent) { OracleParameter parameter = command.Parameters[this.m_parameterName]; parameter.Value = this.Layout.Format(loggingEvent); } public virtual void Prepare(OracleCommand command) { OracleParameter param = command.CreateParameter(); param.ParameterName = this.m_parameterName; if (!this.m_inferType) { param.DbType = this.m_dbType; } if (this.m_precision != 0) { param.Precision = this.m_precision; } if (this.m_scale != 0) { param.Scale = this.m_scale; } if (this.m_size != 0) { param.Size = this.m_size; } command.Parameters.Add(param); } // Properties public DbType DbType { get { return this.m_dbType; } set { this.m_dbType = value; this.m_inferType = false; } } public IRawLayout Layout { get { return this.m_layout; } set { this.m_layout = value; } } public string ParameterName { get { return this.m_parameterName; } set { this.m_parameterName = value; } } public byte Precision { get { return this.m_precision; } set { this.m_precision = value; } } public byte Scale { get { return this.m_scale; } set { this.m_scale = value; } } public int Size { get { return this.m_size; } set { this.m_size = value; } } }
4、实现CustomLayout.cs
ReflectionPatternConverter.cs文件
我浏览 誉满中华 博主的文章时,就想拿来就用呀,可惜博主太忙了 留言没有回复, 而且又急用用就自己下载了源码 参照源码和http://blog.csdn.net/kkkkkxiaofei/article/details/12946913 自己实现了一下,如有问题请留言指出
自定义字段时 一定要 先在 ReflectionPatternConverter.cs 中把自定义字段 映射好
然后 CustomLayout.cs 中
s_globalRulesRegistry = new Hashtable(2);
s_globalRulesRegistry.Add("USERID", typeof(USERIDPatternConverter));
s_globalRulesRegistry.Add("LOGTYPE", typeof(LOGTYPEPatternConverter));
绑定,有多少个自定义字段 就要在这两个cs中对应设置好,layout type 也要指定对地址
5、配置
Global.asax中 Application_Start里添加
log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(Server.MapPath("~") + "\\log4net.config"));
AssemblyInfo.cs 中 添加
[assembly: log4net.Config.XmlConfigurator(ConfigFile = @"log4net.config", Watch = true)]
6、测试一下
简单写个log。cs
private static ILog logOracle = log4net.LogManager.GetLogger("LogOracle");
public static void OracleInfo(Model.SECURITY_LOG4NET logMessage)
{
logOracle.Info(logMessage);
}
//测试写入
Model.SECURITY_LOG4NET model = new Model.SECURITY_LOG4NET();
model.USERID = System.Guid.NewGuid().ToString();
model.LOGTYPE = "Oracle.ManagedDataAccess.Client";
log.OracleInfo(model);
成功写入!
源码给大家做个参考: http://pan.baidu.com/s/1nUFvS 提取码 t45u
本文参考文章:
1、 http://www.cnblogs.com/lightnear/archive/2013/06/04/3117340.html 没有实现自定义 用 Oracle.DataAccess 驱动的
2、http://www.cnblogs.com/hnsongbiao/p/4216147.html#commentform
3、http://stackoverflow.com/questions/29614827/log4net-appender-adonetappender-connectiontype-oracle-manageddataaccess-client
4、http://blog.csdn.net/kkkkkxiaofei/article/details/12946913
5、http://zhoufoxcn.blog.51cto.com/792419/429988/