Asp.net MVC + Redis(hash入库+log4net集成)
博客四元素
既然要写一个博客类的网站,那就应该知道博客的相关信息。
标题 | 作者 | 时间 | 内容 |
---|---|---|---|
title | author | time | content |
因为之前有了解过Redis,所以有点纠结于数据的存储方式,最终决定还是按照书上写的一步一步来,搞完了之后再决定是不是需要做修改。
书中介绍的存储方式如下:
post:count | title | 小猿的博客 |
author | 小猿 | |
time | 2018.5.17 | |
content | 世界如此美妙,我却选择的程序员 |
看的出来博客的所有内容都是以HashSet形式存储的(目前状态),保证存储内容的唯一性取决于post:count的count,这个count应该类似于自增变量。
-
既然是面向对象编程,第一件事肯定是创建一个实体类;
using System; using System.Collections.Generic; using System.Text; using Blog.Common; namespace Blog.Models { public class BLogModel { public BLogModel(string title, string author, DateTime time, string content) { bool flag = true; if (!title.IsNullOrEmpty()) this.title = title; else flag = false; if (!author.IsNullOrEmpty()) this.author = author; else flag = false; if (time == null) flag = false; else this.time = time; if (!content.IsNullOrEmpty()) this.content = content; else flag = false; if(flag==false) { throw new ApplicationException("创建BLogModel实体有必填字段为空"); } } public string title { get; set; } public string author { get; set; } public DateTime time { get; set; } public string content { get; set; } } }
创建这个实体类,我住了定义字段之外主要做了两件事。
①由于在我的SDK里没有找到判空的方法,所以给string写一个扩展方法IsNullOrEmpty;
②每一个博客对象都应该是完整的即每个字段都是必填项,因为使用的是Redis存储也就只能在C#中判断必填项了;
这里还说到另外一个问题,通常情况下需要建立文章缩略名称和文章ID的关联关系。这样做的目的是为了确保文章的唯一性和符合网站网址规范上的一些操作。但是现在还不打算启用这一操作。
-
纠结的入库方式
本来我想的是在控制器中获得数据然后调用RedisCommon的方法获取一个连接对象添加一下就行了,但是代码写了很长一行才搞定exist的判断,有点忍不了。还是决定把所有数据都扔给RedisCommon类叫他来完成这件事情。
首先一打开这个类我就决定先写一个扩展方法(我可能最近比较迷恋写扩展),和之前的ToDic正好相反,这次是把Dictionary<string,string>转化为HashEntry[]
public static HashEntry[] ToHashEntry(this Dictionary<string, string> dic) { List<HashEntry> list = new List<HashEntry>(); foreach (var item in dic.Keys) { list.Add(new HashEntry(item, dic[item])); } return list.ToArray(); }
写这个方法的目的是感觉以后会有很多的字典转成HashEntry数组的情况,使用起来可能比较方便,然后就可以开心的写入库方法了。
public static void SetBLog(BLogModel bLog) { string postCount = GetData().StringIncrement("post:count").ToString(); Dictionary<string, string> dic = new Dictionary<string, string>(); dic.Add("title", bLog.title); dic.Add("author", bLog.author); dic.Add("time", bLog.time.ToString()); dic.Add("content", bLog.content); try { GetData().HashSet("post:"+postCount, dic.ToHashEntry()); } catch (Exception e) { throw e; } }
虽然还不想使用缩略名称和ID关联关系的这个功能,但还是写上吧,省的以后费事。
public static bool SetSlugToId(string slug, string id) { if (!GetData().HashExists("slug.to.id", slug)) { GetData().HashSet("slug.to.id", slug, id); return true; } return false; }
-
集成log4net
log4net就很熟悉了,虽然可以把各种日志都打到数据库中,但是感觉最实用的还是日志文件。
所以起手式还是dotnet cli命令dotnet add package log4net
这里提一下,准备以后有时间了解一下bower,如果可以搞定的话,就玩一下。
然后操作步骤如下文
- 创建一个文件,起名叫log4net.config。
- 在项目起始方法中加载log4net。
- 创建一个全局异常类,其实可以不用这个类的,但是感觉还不错就加进来了。
log4net.config
<?xml version="1.0" encoding="utf-8" ?> <configuration> <!-- This section contains the log4net configuration settings --> <log4net> <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender"> <file value="logfile/" /> <appendToFile value="true" /> <rollingStyle value="Composite" /> <staticLogFileName value="false" /> <datePattern value="yyyyMMdd'.log'" /> <maxSizeRollBackups value="10" /> <maximumFileSize value="1MB" /> <layout type="log4net.Layout.PatternLayout"> <conversionPattern value="%date [%thread] %-5level %logger - %message%newline" /> </layout> </appender> <!-- Setup the root category, add the appenders and set the default level --> <root> <level value="ALL" /> <appender-ref ref="RollingLogFileAppender" /> </root> </log4net> </configuration>
在Startup文件中加载log4net,其实比原来就多加了三行代码。
这里需要说的就是创建静态ILoggerRepository的时候需要导包,最机智的方法自然就是dotnet new sln创建一个解决方案,把项目填进去,用VS解决这件事。
public static ILoggerRepository repository{get;set;} public Startup(IConfiguration configuration) { Configuration = configuration; //加载log4net日志配置文件 repository = LogManager.CreateRepository("NETCoreRepository"); XmlConfigurator.Configure(repository, new FileInfo("log4net.config")); }
全局异常类
using log4net; using Microsoft.AspNetCore.Mvc.Filters; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Blog { public class HttpGlobalExceptionFilter : IExceptionFilter { private ILog log = LogManager.GetLogger(Startup.repository.Name, typeof(HttpGlobalExceptionFilter)); public void OnException(ExceptionContext context) { log.Error(context.Exception); } } }
log的使用方式,一般情况下吧log对象放在基类中就够用了。
protected static ILog log = LogManager.GetLogger(Startup.repository.Name, typeof(HttpGlobalExceptionFilter)); log.Info("log test fisish");