EntityFramework Core进行读写分离最佳实践方式,了解一下(二)?
前言
写过上一篇关于EF Core中读写分离最佳实践方式后,虽然在一定程度上改善了问题,但是在评论中有的指出更换到从数据库,那么接下来要进行插入此时又要切换到主数据库,同时有的指出是否可以进行底层无感知操作,这确实是个问题,本文继续进行引路,进一步改善评论中问题的指出,至于实现更复杂的逻辑可自行实现,感谢你们非常棒的评论,使得本文由此而生。
EF Core读写分离进一步完善
如评论前辈们指出在EF 6.x中我们知道有IDbCommandInterceptor接口,我们可对执行的SQL语句进行拦截,从而可自定义实现我们想要的需求,虽然在EF Core中却没有拦截器特性的实现,但是针对此特性的实现DiagnosticSource记录跟踪类来实现等效于拦截器的实现,当前DiagnosticSource使用文档尚未完善,估计还得等待一段时间,接下来我们来看看如何实现。在DiagnosticSource包中有DiagnosticListener类,我们通过此类来跟踪记录,如果执行的EF Core包,那么我们将利用DiagnosticListener进行订阅,订阅到之后我们拿到跟踪命令,从而实现无感知更换数据库,代码如下:
public class DbCommandInterceptor : IObserver<KeyValuePair<string, object>>
{
private const string masterConnectionString = "data source=WANGPENG;User Id=sa;Pwd=sa123;initial catalog=Demo1;integrated security=True;";
private const string slaveConnectionString = "data source=WANGPENG;User Id=sa;Pwd=sa123;initial catalog=Demo2;integrated security=True;";
public void OnCompleted()
{
} public void OnError(Exception error)
{
} public void OnNext(KeyValuePair<string, object> value)
{
if (value.Key == RelationalEventId.CommandExecuting.Name)
{
var command = ((CommandEventData)value.Value).Command;
var executeMethod = ((CommandEventData)value.Value).ExecuteMethod; if (executeMethod == DbCommandMethod.ExecuteNonQuery)
{
ResetConnection(command, masterConnectionString);
}
else if (executeMethod == DbCommandMethod.ExecuteScalar)
{
ResetConnection(command, slaveConnectionString);
}
else if (executeMethod == DbCommandMethod.ExecuteReader)
{
ResetConnection(command, slaveConnectionString);
}
}
} void ResetConnection(DbCommand command, string connectionString)
{
if (command.Connection.State == ConnectionState.Open)
{
if (!command.CommandText.Contains("@@ROWCOUNT"))
{
command.Connection.Close();
command.Connection.ConnectionString = connectionString;
}
}
if (command.Connection.State == ConnectionState.Closed)
{
command.Connection.Open();
}
}
}
这里存在一个问题,上述 command.CommandText.Contains("@@ROWCOUNT") 代码,因为在进行添加操作时,会返回主键,那么此时会进行查询,所以暂时没有更好的方式是确认主-从数据库。
public class CommandListener : IObserver<DiagnosticListener>
{
private readonly DbCommandInterceptor _dbCommandInterceptor = new DbCommandInterceptor(); public void OnCompleted()
{
} public void OnError(Exception error)
{
} public void OnNext(DiagnosticListener listener)
{
if (listener.Name == DbLoggerCategory.Name)
{
listener.Subscribe(_dbCommandInterceptor);
}
}
}
上述 DbLoggerCategory.Name 也就是 Microsoft.EntityFrameworkCore ,通过监控的包是Microsoft.EntityFrameworkCore,则进行订阅,最后我们在startup中进行注册该监听类。
DiagnosticListener.AllListeners.Subscribe(new CommandListener());
接下来我们通过动态图来看看最终实际效果,主-从复制依然是通过SQL Server发布-订阅的方式来同步数据。在控制器中,我们只利用demo1上下文来添加和查询数据,当查询时更换到从数据库,此时已是无感知(请见上一篇),如下:
[HttpGet("index")]
public IActionResult Index()
{
var blogs = _demo1DbContext.Blogs.ToList();
return View(blogs);
}
[HttpGet("create")]
public IActionResult CreateDemo1Blog()
{
var blog = new Blog()
{
Name = "demoBlog1",
Url = "http://www.cnblogs.com/createmyslef"
};
_demo1DbContext.Blogs.Add(blog);
_demo1DbContext.SaveChanges();
return RedirectToAction(nameof(Index));
}

总结
本文只是在上一篇的基础上进一步改善了读写分离的操作,得益于github上有提出可通过跟踪记录来解决,通过跟踪记录从底层出发来完善读写分离操作,我们可拿到底层实现的命令以及其他和EF 6.x中利用拦截器等效,至于更加复杂的逻辑可自行实现。
EntityFramework Core进行读写分离最佳实践方式,了解一下(二)?的更多相关文章
- EntityFramework Core进行读写分离最佳实践方式,了解一下(一)?
前言 本来打算写ASP.NET Core MVC基础系列内容,看到有园友提出如何实现读写分离,这个问题提的好,大多数情况下,对于园友在评论中提出的问题,如果是值得深究或者大多数同行比较关注的问题我都会 ...
- EF Core 实现读写分离的最佳方案
前言 公司之前使用Ado.net和Dapper进行数据访问层的操作, 进行读写分离也比较简单, 只要使用对应的数据库连接字符串即可. 而最近要迁移到新系统中,新系统使用.net core和EF Cor ...
- EF core 实现读写分离解决方案
我们公司2019年web开发已迁移至.NET core,目前有部分平台随着用户量增加,单一数据库部署已经无法满足我们的业务需求,一直在寻找EF CORE读写分离解决方案,目前在各大技术论坛上还没找到很 ...
- 探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式
如果你的网站需要被世界各地的人访问,访问者会使用各种不同的语言和文字书写习惯,那么创建一个支持多语言的网站就是十分必要的了,这一篇文章就讲述怎么快速合理的创建网站对多语言的支持.接下来通过一个实例来讲 ...
- .NET Core调用WCF的最佳实践
现在.NET Core貌似很火,与其他.NET开发者交流不说上几句.NET Core都感觉自己落伍了一样.但是冷静背后我们要也看到.NET Core目前还有太多不足,别的不多说,与自家的服务框架WCF ...
- React 代码共享最佳实践方式
任何一个项目发展到一定复杂性的时候,必然会面临逻辑复用的问题.在React中实现逻辑复用通常有以下几种方式:Mixin.高阶组件(HOC).修饰器(decorator).Render Props.Ho ...
- Fibonacci(斐波那契数列)的最佳实践方式(JavaScript)
1)低级版本 var fibonacci = function(n) { if (n == 0 || n == 1) { return n; } else { return fibonacci(n - ...
- Entity Framework Core 实现读写分离
在之前的版本中我们可用构造函数实现,其实现在的版本也一样,之前来构造连接字符串,现在相似,构造DbContextOptions<T> 代码如下: public SContext(Maste ...
- SQL Server、MySQL主从搭建,EF Core读写分离代码实现
一.SQL Server的主从复制搭建 1.1.SQL Server主从复制结构图 SQL Server的主从通过发布订阅来实现 1.2.基于SQL Server2016实现主从 新建一个主库&quo ...
随机推荐
- .NET微服务调查结果
.NET Core就是专门针对模块化的微服务架构而设计, 在2018年国庆时间展开.NET微服务的使用情况,本次调查我们总计收到了来自378个开发者的调查.从落地现状.架构体系.未来趋势等方面对微服务 ...
- 磁盘阵列raid类型及含义
raid0: 多块盘同时进行读写: 优点是读写效率高,缺点是没有数据冗余: 最少需要两块盘. raid1: 将数据盘都做镜像: 优点是有数据冗余:缺点是读写效率低,磁盘利用率低: 最少需要两块盘. r ...
- 2. VIM 系列 - 初探vim配置文件
目录 配置文件 .vimrc 基本配置 tab 键设置 热键配置 配置文件 刚安装vim默认配置,功能是很简单的,vim的功能很多是需要配置开启的. .vimrc 使用vim打开配置文件~/.vimr ...
- scala获取某个时间间隔的时间
原始 dataFrame : //获取前7天的时间long类型 def getDaytimeTime(day:Int): Long = { val cal = Calendar.getInstance ...
- Flink中的Time
戳更多文章: 1-Flink入门 2-本地环境搭建&构建第一个Flink应用 3-DataSet API 4-DataSteam API 5-集群部署 6-分布式缓存 7-重启策略 8-Fli ...
- windows环境设置mysql自动备份(测试成功)
00.背景介绍 最近做了个小程序,使用的是mysql数据库,涉及到将程序数据备份的事:虽然大部分数据库客户端工具都具有备份功能,但并不能做到定期自动备份:在Windows环境下,手工备份MySQL是很 ...
- leetcode 链表类型题目解题总结
最基础的方式要做到非常熟练,要熟练到不思考就能写,但又需明白各处的要求和陷阱 合并两个有序链表的操作,在前面加上一个初始节点,注意while循环和退出时的处理,理解如何处理其中一个链表遍历完的情况 L ...
- 杂牌机搞机之旅(二)————移植TWRP第三方Recovery并刷入
原本想把杂牌机作为android破解和开发的测试机,破解的话肯定是安装框架的嘛,毕竟有些是要涉及到脱壳 . 但是,我尝试安装xposed的时候,手机卡在了开机界面,也就是magisk出现了错误,如果想 ...
- 【MySQL】MySQL的执行计划及索引优化
我们知道一般图书馆都会建书目索引,可以提高数据检索的效率,降低数据库的IO成本.MySQL在300万条记录左右性能开始逐渐下降,虽然官方文档说500~800w记录,所以大数据量建立索引是非常有必要的. ...
- Dotspatial 要素重叠分析
private void toolStripButton30_Click(object sender, EventArgs e) { //面状重叠分析 if (mapMain.Layers.Count ...