一步步学习EF Core(2.事务与日志)
上节我们留了一个问题,为什么EF Core中,我们加载班级,数据并不会出来
其实答案很简单,~ 因为在EF Core1.1.2 中我们在EF6.0+中用到的的延迟加载功能并没有被加入,不过在EF Core 2.0中,这个功能将回归
而且这个功能是否需要被加入进去,社区也在激烈的讨论当中,有兴趣的可以去看看:
https://github.com/aspnet/EntityFramework/issues/3797
那么我们该如何加载关联的班级呢?.
直接通过Linq join当然是可以的. 我们也可以通过贪婪加载来获取,修改查询代码如下:
public IActionResult ListView()
{
return View(_context.UserTable.Include(a=>a.Class).ToList());
}
效果如下:

下面我们开始今天的内容
关于EF Core的事务,其实与EF 6.x几乎一样,代码如下:
using (var tran = _context.Database.BeginTransaction())
{
try
{
_context.ClassTable.Add(new ClassTable { ClassName = "AAAAA", ClassLevel = });
_context.ClassTable.Add(new ClassTable { ClassName = "BBBBB", ClassLevel = });
_context.SaveChanges();
throw new Exception("模拟异常");
tran.Commit();
}
catch (Exception)
{
tran.Rollback();
// TODO: Handle failure
}
}
在异常中Rollback即可回滚,我这里的写法,其实有点无耻.
不过目的是告诉大家,要在Commit之前回滚.
不然会得到一个异常:This SqlTransaction has completed; it is no longer usable.”
下面我们来讲一下关于EF Core中的日志
我们知道,在ASP.NET Core中,大量的使用了IOC的手法来注入我们所需要的类.
EF Core其实也一样,.
首先我们需要创建一个EF日志类,继承Microsoft.Extensions.Logging.ILogger
如下:
private class EFLogger : ILogger
{
private readonly string categoryName; public EFLogger(string categoryName) => this.categoryName = categoryName; public bool IsEnabled(LogLevel logLevel)
{
return true;
} public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{ Debug.WriteLine($"时间:{DateTime.Now.ToString("o")} 日志级别: {logLevel} {eventId.Id} 产生的类{this.categoryName}");
DbCommandLogData data = state as DbCommandLogData;
Debug.WriteLine($"SQL语句:{data.CommandText},\n 执行消耗时间:{data.ElapsedMilliseconds}"); } public IDisposable BeginScope<TState>(TState state)
{
return null;
}
}
我这里面的Debug.WriteLine是为了方便调试.
正常情况下当然是写入日志文件,可以用Log4Net
然后,我们创建一个空的日志类(用来过滤不需要记录的日志)如下:
private class NullLogger : ILogger
{
public bool IsEnabled(LogLevel logLevel)
{
return false;
} public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
{ } public IDisposable BeginScope<TState>(TState state)
{
return null;
}
}
然后,我们创建一个日志提供类(注入用,EF Core1.0版本注意注释),如下:
public class MyFilteredLoggerProvider : ILoggerProvider
{
public ILogger CreateLogger(string categoryName)
{
// NOTE: 这里要注意,这是 EF Core 1.1的使用方式,如果你用的 EF Core 1.0, 就需把IRelationalCommandBuilderFactory替换成下面的类
// Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory if (categoryName == typeof(IRelationalCommandBuilderFactory).FullName)
{
return new EFLogger(categoryName);
} return new NullLogger();
}
public void Dispose()
{ }
}
然后我们到Startup.cs的Configure()方法中注入我们的日志提供类
代码如下:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{ loggerFactory.AddProvider(new MyFilteredLoggerProvider());
....省略
}
运行程序,得到如下调试信息:

至此,我们就完成了日志的记录工作.
那么问题来了,在Asp.NET core中,我们可以这样注入进行日志记录.
如果在别的项目(比如控制台)中,怎么办?
下面就来解决这个问题.
在非Asp.NET core的程序中,我们需要把日志提供器从上下文里注入如下:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{ base.OnConfiguring(optionsBuilder);
LoggerFactory loggerFactory = new LoggerFactory();
loggerFactory.AddProvider(new MyFilteredLoggerProvider());
//注入
optionsBuilder.UseLoggerFactory(loggerFactory); }
写在最后,其实在EF Core的路线图中,我们可以看到,在2.0的版本将会提供一个更简单的日志记录方式
这段话是在(Features originally considered but for which we have made no progress and are essentially postponed)之后的:
..上面翻译过来的大概意思就是:我们原来考虑会加入的功能,但是现在并没有进展,基本要推迟的特点.(..总结三个字,然并卵)
- Simple Logging API (#1199) - We want a simple way to log the SQL being executed (like
Database.Logfrom EF6.x). We also want a simple way to view everything being logged. - 嗯..翻译过来的意思就是..我们想提供一个更简单的日志记录,比如像EF6.x中的
Database.Log 这样...()
还有一个比较有趣的东西如下:
在High priority features(高度优先的功能)中还有一段话:
- Simple command interception provides an easy way to read/write commands before/after they are sent to the database.
- 简单的命令拦截,将提供在发送到数据库之前/之后读取/写入命令的简单方法
我觉得这个有点类似于EF6.x的IDbCommandInterceptor.
感兴趣的朋友可以去了解一下,我之前的博文也有介绍:
EntityFramework的多种记录日志方式,记录错误并分析执行时间过长原因(系列4)
好了,就说这么多.
一步步学习EF Core(2.事务与日志)的更多相关文章
- [转]一步步学习EF Core(2.事务与日志)
本文转自:http://www.cnblogs.com/GuZhenYin/p/6862505.html 上节我们留了一个问题,为什么EF Core中,我们加载班级,数据并不会出来 其实答案很简单,~ ...
- 一步步学习EF Core(1.DBFirst)
前言 很久没写博客了,因为真的很忙,终于空下来,打算学习一下EF Core顺便写个系列, 今天我们就来看看第一篇DBFirst. 本文环境:VS2017 Win7 .NET Core1.1 ...
- 一步步学习EF Core(3.EF Core2.0路线图)
前言 这几天一直在研究EF Core的官方文档,暂时没有发现什么比较新的和EF6.x差距比较大的东西. 不过我倒是发现了EF Core的路线图更新了,下面我们就来看看 今天我们来看看最新的EF Cor ...
- EF Core学习Code First
下面通过实例来学习EF Core Code First,也就是通过EF Core迁移来完成从模型生成数据库. 本实例使用EntityFrameworkCore SQLite 数据库进行介绍,大家也可以 ...
- EF Core 2.0中Transaction事务会对DbContext底层创建和关闭数据库连接的行为有所影响
数据库 我们先在SQL Server数据库中建立一个Book表: CREATE TABLE [dbo].[Book]( ,) NOT NULL, ) NULL, ) NULL, ) NULL, [Cr ...
- [翻译 EF Core in Action 2.3] 理解EF Core数据库查询
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- [翻译 EF Core in Action 2.2] 创建应用程序的数据库上下文
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
- EF Core in Action 中文翻译 第一部分导航
Entityframework Core in action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Core ...
- [翻译 EF Core in Action 2.1] 设置一个图书销售网站的场景
Entity Framework Core in Action Entityframework Core in action是 Jon P smith 所著的关于Entityframework Cor ...
随机推荐
- Laravel查询构造器的使用方法整理
1.结果集 1.1从一张表获取所有行,get方法获取所有行 $users = DB::table('users')->get(); 获取列的值 foreach ($users as $user) ...
- POPTEST老李分享修改dns ip的vbs代码
POPTEST老李分享修改dns ip的vbs代码 poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨 ...
- Java中log4j的使用
前言 距离上一篇文章又过去好长时间了,这段时间一直忙于工作,已经从net彻底转向Java了.工作也慢慢的步入正轨了,自己独自完成了一个小项目,不过工作中遇到了一些问题,还是得到了同学和同事的帮助.本来 ...
- 微信小程序登录数据解密以及状态维持
学习过小程序的朋友应该知道,在小程序中是不支持cookie的,借助小程序中的缓存我们也可以存储一些信息,但是对于一些比较重要的信息,我们需要通过登录状态维持来保存,同时,为了安全起见,用户的敏感信息, ...
- 理解C++中的头文件和源文件的作用【转】
一.C++编译模式通常,在一个C++程序中,只包含两类文件--.cpp文件和.h文件.其中,.cpp文件被称作C++源文件,里面放的都是C++的源代码:而.h文件则被称作C++头文件,里面放的也是C+ ...
- 解决移动端click点击问题
下载地址:https://github.com/ftlabs/fastclick 1,为什么移动端点击会有300ms的延迟呢? 从点击屏幕上的元素到触发元素的 click 事件,移动浏览器会有大约 3 ...
- hexo工具介绍及使用方法
Hexo is a fast, simple & powerful blog framework 安装方法:npm install hexo-cli -g; require:node.js g ...
- Java线程池(ThreadPool)详解
线程五个状态(生命周期): 线程运行时间 假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间. 如果:T1 + T3 远大于 T2,则可以 ...
- 深入理解css中vertical-align属性
一.为什么要写这篇文章 今天看到一个问题: 两个div 都设置 display:inline-block,正常显示:但是在第二个div中加一个块级元素或者内联元素,显示就变了个样,为什么? <m ...
- iOS UITableViewCell点击时子视图背景透明的解决方法
在做iOS项目的开发中,UITableView控件的应用十分广泛.在进行自定义UITableViewCell时,经常遇到这样的问题:在UITableViewCell上面添加了一个有背景颜色的子视图,当 ...