前言

本节我们来看看ASP.NET Core MVC中比较常用的功能,对于导入和导出目前仍在探索中,项目需要自定义列合并,所以事先探索了如何在ASP.NET Core MVC进行导入、导出,更高级的内容还需等我学习再给出。

EntityFramework Core

在学习ASP.NET Core MVC之前我们来看看在EF Core中如何更新对象指定属性,这个问题之前我们已经探讨过,但是还是存在一点问题,请往下看。

        public void Update(T entity, params Expression<Func<T, object>>[] properties)
{
_context.Entry(entity).State = EntityState.Unchanged;
foreach (var property in properties)
{
var propertyName = ExpressionHelper.GetExpressionText(property);
_context.Entry(entity).Property(propertyName).IsModified = true;
}
}

上述方法可以用来更新对象指定属性,使用lambda来指定需要更新的属性,如下:

        [HttpGet("[action]")]
public IActionResult Index()
{
var blog = new Blog() { Id = , Name = "Jeffcky1" };
_blogRepository.Update(blog, d => d.Name);
_blogRepository.SaveChanges();
}

但是当更新数值类型时会解析不到该属性,如下:

             var blog = new Blog() { Id = , Count =  };
_blogRepository.Update(blog, d => d.Count);
_blogRepository.SaveChanges();

此时得到该属性名称为空字符串

lambda为何解析不到呢?原来它进行了Convert如下:

既然是将其转换成了Convert,那么在表达式树中应该用其节点类型,如下:

此时我们需要判断其节点类型是否已经经过Convert即可,最终代码如下:

        public void Update(T entity, params Expression<Func<T, object>>[] properties)
{ EntityEntry<T> entry = _context.Entry(entity);
entry.State = EntityState.Unchanged;
foreach (var property in properties)
{
string propertyName = "";
Expression bodyExpression = property.Body;
if (bodyExpression.NodeType == ExpressionType.Convert && bodyExpression is UnaryExpression)
{
Expression operand = ((UnaryExpression)property.Body).Operand;
propertyName = ((MemberExpression)operand).Member.Name;
}
else
{
propertyName = ExpressionHelper.GetExpressionText(property);
}
entry.Property(propertyName).IsModified = true;
}
}

此时将能正确解析到数值类型名称,如下:

为何要封装这一层,只是不想首先查询出对象然后再来进行更新属性,其两步操作合并为一步岂不爽哉。当然我们也可以不通过lambda来实现,直接给出属性集合,然后遍历即可,大概如下:

        public void Update(T entity, params object[] properties)
{
_context.ChangeTracker.TrackGraph(entity, e =>
{
e.Entry.State = EntityState.Unchanged;
if ((e.Entry.Entity as T) != null)
{
foreach (var p in properties)
{
_context.Entry(e.Entry.Entity as T).Property(p.ToString()).IsModified = true;
} }
});
}

Serilog日志输出

目前比较流行的日志框架则是Log4net、NLog,之前也一直用的Log4net,但是在.net core中已经内置了日志框架Serilog,在github上也已加星不少,想必比较强大,既然这样为何不使用内置的呢,免去再用其他日志框架还要配置的麻烦。

创建默认项目在Startup中已经注入日志,如下:

loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();

当利用dotnet.exe调试时在控制台会显示调试各种信息,要是直接运行那该如何呢?在web中的配置文件web.config中,如下:

 <aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false"/>
</system.webServer>

我们需要设置 stdoutLogEnabled="true" 来启动调试,此时运行项目你会发现屁都没有,此时我们查看windows日志发现根本无法创建文件夹,想必是没有权限的缘故。

此时我们需要手动创建logs文件夹,最终运行程序则会自动将所有信息写入到日志文件中,如下:

是不是这样就完了呢,这样设置则会将所有信息都会写入日志那样岂不是额外做些无用功,看看如下生成的日志。

光说不练假把式,来,我们来实现一个,让你见识见识Serilog的强大。先定义一个自定义输出格式的Option并创建输出日志文件夹。

    public class JeffckyLogOptions
{
public string LogPath { get; set; } = @"C:\Jeffcky_StudyEFCore\logs"; public string PathFormat { get; set; } public static void EnsurePreConditions(JeffckyLogOptions options)
{
if (options == null)
{
throw new ArgumentNullException(nameof(options));
} if (string.IsNullOrWhiteSpace(options.LogPath))
{
throw new ArgumentException("系统日志文件存储路径未配置", nameof(options.LogPath));
} if (string.IsNullOrWhiteSpace(options.PathFormat))
{
throw new ArgumentException("系统日志文件名称未配置", nameof(options.PathFormat));
} if (!Directory.Exists(options.LogPath))
{
Directory.CreateDirectory(options.LogPath);
}
}
}

内置实现日志的接口.net core已经给出,所以我们需要获取内置日志接口服务并实现自定义扩展方法。

app.ApplicationServices.GetService(typeof(ILoggerFactory));

此时上述app来源于 IApplicationBuilder 此时我们则只需要实现该接口的自定义扩展方法。我们开始下载Serilog程序包

此时我们需要对日志通过 LoggerConfiguration 类进行初始化配置。

接下来则是将日志写到文件中我们可以自定义格式,此时再下载如下程序包。

里面有个 RollingFile 方法来自定输出日志模板,自此我们就有了如下代码:

          var serilog = new LoggerConfiguration()
.MinimumLevel.Debug()
.Enrich.FromLogContext()
.WriteTo.RollingFile(Path.Combine(options.LogPath, options.PathFormat),
outputTemplate: "[{Timestamp:HH:mm:ss} {Level}] {Message}{NewLine}{Exception}");

我们获取.net core内置的日志接口服务。

 ILoggerFactory loggerFactory = (ILoggerFactory)app.ApplicationServices.GetService(typeof(ILoggerFactory));

同时设置我们输出日志的路径选项。

JeffckyLogOptions.EnsurePreConditions(options);

接下来将Serilog创建的日志添加到内置日志服务中,如下:

 loggerFactory.AddSerilog(serilog.CreateLogger());

当然上述AddSerilog方法时扩展方法,此时我们仍需要添加如下扩展程序包:

最后还差一步则是日志的生命周期,灰常重要,为什么说灰常重要,我们要确保当程序关闭时或者系统出问题时所有在内存缓冲区的日志都将输送到日志文件夹中,如下:

            // Ensure any buffered events are sent at shutdown
IApplicationLifetime appLifetime = (IApplicationLifetime)app.ApplicationServices.GetService(typeof(IApplicationLifetime));
if (appLifetime != null)
{
appLifetime.ApplicationStopped.Register(Log.CloseAndFlush);
}

一气呵成,最终我们在Startup的如下方法中进行调用即可:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{...}

利用Serilog添加自定日志格式输出,进行如下调用:

            app.UseJeffckySelfDefineLog(new JeffckyLogOptions()
{
LogPath = Configuration[nameof(JeffckyLogOptions.LogPath)],
PathFormat = "Jeffcky_StudyEFCore_{Date}.log"
});

当然还有其他强大功能,比如Serilog中可以获取到上下文,这样的话我们就可以过滤对于那个应用程序使用对应的日志输出级别以及其他,如下:

                serilog = serilog.Filter.ByIncludingOnly((e) =>
{
var context = e.Properties["SourceContext"].ToString(); return (context.StartsWith("\"Your Applicion Name") ||
e.Level == LogEventLevel.Warning ||
e.Level == LogEventLevel.Error ||
e.Level == LogEventLevel.Fatal);
});

说一千到一万,出现结果才是真理,我们一起来看看。

看看日志输出信息,你会看到干净的日志输出。

总结

本节我们详细讲解了.net core中新生代日志框架-Serilog,别抱着Log4net不放了,Serilog你值得拥有,跟着老大一直学习中,涨涨见识!因为项目中会用到批量导入和导出,所以在研究导出、导入,下节可能会讲到导入、导出在ASP.NET Core MVC中,也有可能会讲SQL Server中的最后几节关于死锁的内容,不管怎样都是在积累知识,你说呢,敬请期待!

ASP.NET Core MVC之Serilog日志处理,你了解多少?的更多相关文章

  1. asp.net core MVC 全局过滤器之ExceptionFilter异常过滤器(一)

    本系类将会讲解asp.net core MVC中的内置全局过滤器的使用,将分为以下章节 asp.net core MVC 过滤器之ExceptionFilter异常过滤器(一) asp.net cor ...

  2. asp.net core MVC 过滤器之ActionFilter过滤器(二)

    本系类将会讲解asp.net core MVC中的内置全局过滤器的使用,将分为以下章节 asp.net core MVC 过滤器之ExceptionFilter过滤器(一) asp.net core ...

  3. ASP.NET Core MVC+EF Core从开发到部署

    笔记本电脑装了双系统(Windows 10和Ubuntu16.04)快半年了,平时有时间就喜欢切换到Ubuntu系统下耍耍Linux,熟悉熟悉Linux命令.Shell脚本以及Linux下的各种应用的 ...

  4. Asp.Net Core MVC框架内置过滤器

    第一部分.MVC框架内置过滤器 下图展示了Asp.Net Core MVC框架默认实现的过滤器的执行顺序: Authorization Filters:身份验证过滤器,处在整个过滤器通道的最顶层.对应 ...

  5. ASP.NET Core MVC内置服务的使用

    ASP.NET Core中的依赖注入可以说是无处不在,其通过创建一个ServiceCollection对象并将服务注册信息以ServiceDescriptor对象的形式添加在其中,其次针对Servic ...

  6. ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 02. Web Host 的默认配置

    视频地址: https://www.bilibili.com/video/av38392956/?p=2 语雀 https://www.yuque.com/yuejiangliu/dotnet/ixt ...

  7. 从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用

    标题:从零开始实现ASP.NET Core MVC的插件式开发(六) - 如何加载插件引用. 作者:Lamond Lu 地址:https://www.cnblogs.com/lwqlun/p/1171 ...

  8. asp.net core MVC 过滤器之ExceptionFilter过滤器(一)

    简介 异常过滤器,顾名思义,就是当程序发生异常时所使用的过滤器.用于在系统出现未捕获异常时的处理. 实现一个自定义异常过滤器 自定义一个异常过滤器需要实现IExceptionFilter接口 publ ...

  9. 如何在 ASP.Net Core 中使用 Serilog

    记录日志的一个作用就是方便对应用程序进行跟踪和排错调查,在实际应用上都是引入 日志框架,但如果你的 日志文件 包含非结构化的数据,那么查询起来将是一个噩梦,所以需要在记录日志的时候采用结构化方式. 将 ...

随机推荐

  1. sysctl.conf和limit.conf备忘待查

    #################################limits.conf设置################################### #修改最大进程和最大文件打开数限制v ...

  2. 两台机子的repcached Memcache 的安装与实验

    安装memcached前先要确定系统是否安装了gcc: 1.解压安装包: tar -zxf memcached-1.2.8-repcached-2.2.tar.gz 2.编译: 系统应安装了libev ...

  3. C#中的协变OUT和逆变

    泛型接口和泛型委托中经常使用可变性 in  逆变,out  协变 从 list<string>转到list<object> 称为协变 (string 从object 派生,那么 ...

  4. numpy 安装

    sudo apt-get install python-scipy sudo apt-get install python-numpy sudo apt-get install python-matp ...

  5. MindManager 安装注册

    正版现在998元,对于个人用户来说是不是太贵了.直接下载的还不能打开,挺奇怪.

  6. dev中TreeList的应用(转)

    如果需要在单元格添加时则用TreeList如果只是单纯读取数据或检索数据时则用GridControl 1.如果点击添加 时则添加TreeList的节点: protected internal void ...

  7. ubuntu vi编辑insert时上下左右建为ABCD

    ubuntu  在vi编辑insert时上下左右建不能移动光标而是输出ABCD,backspace也不能起删除作用, 开始我退出insert模式就能够移动和删除了,不过这样太麻烦很不适应, 只要一次执 ...

  8. pureMVC简单示例及其原理讲解五(Facade)

    本节将讲述Facade,Proxy.Mediator.Command的统一管家.自定义Facade必须继承Facade,在本示例中自定义Facade名称为ApplicationFacade,这个名称也 ...

  9. Canvas createImageData

    createImageData() 方法创建新的空白 ImageData 对象.新对象的默认像素值 transparent black. 对于 ImageData 对象中的每个像素,都存在着四方面的信 ...

  10. 第一篇:CUDA 6.0 安装及配置( WIN7 64位 / 英伟达G卡 / VS2010 )

    前言 本文讲解如何在VS 2010开发平台中搭建CUDA开发环境. 当前配置: 系统:WIN7 64位 开发平台:VS 2010 显卡:英伟达G卡 CUDA版本:6.0 若配置不同,请谨慎参考本文. ...