随笔 - 394  文章 - 0  评论 - 946  阅读 - 143万 
问题1: 在公司进行log4net写入服务器配置的时候,一切正常,但是在家里的机器上,就频繁出现这个问题:
SQL Server 2008 报错:已成功与服务器建立连接,但是在登录前的握手期间发生错误 
并且这种错误是随机性的,在log4net往数据库插入几条的时候,没问题,但是插入次数一多起来,就频繁报这个错误。后来没办法,网上搜罗了一圈,最终发现了解决方案:
 
将相关的TCP参数都设置为启动之后,就再没遇到过问题。
 
 问题2,log4net配置都正确,但是一直无法写入数据库。
这个问题困扰了好久,最终得以解决,大家就看看我的解决代码吧,我也懒得帖步骤了。
 
配置文件如下:


注意上面配置代码中:log4net.Layout.PatternLayout 是log4net本身提供的配置模板,如果你有的字段需要用到其本身的模板字段的话,就可以使用。

还需要注意这段话: <conversionPattern value="%property{s_id}" />,它表明,我们将会利用log4net提供的已有的property转义模板来识别我们的字段。

 

但是如果你有自定义字段的话,你就需要自己写layout和converter了。在上面的配置文件中,content,s_id,t_id是我自定义的三个字段,如何让这三个字段也写入到数据库呢,我们一步一步来配置。

首先,需要将三个自定义字段放到一个entity类中:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
namespace FuNong.Framework.Logger
{
    public class LogContent
    {
        public LogContent(string content, string s_id, string t_id)
        {
            this.content = content;
            this.s_id = s_id;
            this.t_id = t_id;
        }
 
        public string content { get; set; }
 
        public string s_id { get; set; }
        public string t_id { get; set; }
    }
}

 

 然后,定义我们自己的layout,由于我们使用了property字段模板,所以我们这里需要按照如下方式添加:

1
2
3
4
5
6
7
8
9
10
namespace FuNong.Framework.Logger
{
    public class CustomLayout:PatternLayout
    {
        public CustomLayout()
        {
            this.AddConverter("property", typeof(XPatternConverter));
        }
    }
}

 

最后,就是我们的Converter实现了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
namespace FuNong.Framework.Logger
{
    public class XPatternConverter : PatternLayoutConverter
    {
        protected override void Convert(System.IO.TextWriter writer, log4net.Core.LoggingEvent loggingEvent)
        {
            if (this.Option != null)
            {
                // Write the value for the specified key
                WriteObject(writer, loggingEvent.Repository, LookupProperty(Option, loggingEvent));
            }
            else
            {
                // Write all the key value pairs
                WriteDictionary(writer, loggingEvent.Repository, loggingEvent.GetProperties());
            }
 
        }
 
        /// <summary>
        /// 通过反射获取传入的日志对象的某个属性的值
        /// </summary>
        /// <param name="property"></param>
        /// <returns></returns>
        private Object LookupProperty(String property, log4net.Core.LoggingEvent loggingEvent)
        {
            Object propertyValue = String.Empty;
            PropertyInfo propertyInfo;
 
            propertyInfo = loggingEvent.MessageObject.GetType().GetProperty(property);
            if (propertyInfo != null)
            {
                propertyValue = propertyInfo.GetValue(loggingEvent.MessageObject, null);
            }
            return propertyValue;
        }
 
    }
}

 从上面代码,我们可以看到,log4net会通过反射来识别我们logContent这个entity中的字段,然后逐个赋值,再写到数据库的。

下面我们稍微包装一下:

1
2
3
4
5
6
7
8
9
10
11
namespace FuNong.Framework.Logger
{
    public interface ILoggerService
    {
        void Debug(object message);
        void Error(object message);
        void Fatal(object message);
        void Info(object message);
        void Warn(object message);
    }
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
namespace FuNong.Framework.Logger
{
    public class LoggerService:ILoggerService
    {
        public LoggerService()
        {
            log4net.Config.XmlConfigurator.Configure();
            logger = LogManager.GetLogger(typeof(LoggerService));
        }
 
        private readonly ILog logger;
 
        public void Info(object message)
        {
            logger.Info(message);
        }
        public void Warn(object message)
        {
            logger.Warn(message);
        }
        public void Debug(object message)
        {
            logger.Debug(message);
        }
        public void Error(object message)
        {
            logger.Error(message);
        }
        public void Fatal(object message)
        {
            logger.Fatal(message);
        }
        
    }
}

 

由于我用了autofac做ioc,所以我们就直接看使用方法吧:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
protected override void OnAuthorization(AuthorizationContext filterContext)
      {
          if (auth)
          {
              var collection = cookie.GetCookieCollection("FuNong.UserInfo.Login");
              if (collection == null)
              {
                  logger.Warn(new LogContent("用户登陆信息提取失败,将会跳转到登陆界面...", "1", "2"));
                  filterContext.Result = new RedirectResult("Home/Login");
              }
              else
              {
                  logger.Info(new LogContent("用户验证成功,请继续之前操作...","1","2"));
              }
          }
      }

 

这样,当我们运行起来后,我们就发现,程序已经将数据写入数据库了。

 

整个配置不难,但是细节挺多,稍微不小心,就可能导致写入不到数据库。

posted on   程序诗人  阅读(1322)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示