前言

写过上一篇关于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进行读写分离最佳实践方式,了解一下(二)?的更多相关文章

  1. EntityFramework Core进行读写分离最佳实践方式,了解一下(一)?

    前言 本来打算写ASP.NET Core MVC基础系列内容,看到有园友提出如何实现读写分离,这个问题提的好,大多数情况下,对于园友在评论中提出的问题,如果是值得深究或者大多数同行比较关注的问题我都会 ...

  2. EF Core 实现读写分离的最佳方案

    前言 公司之前使用Ado.net和Dapper进行数据访问层的操作, 进行读写分离也比较简单, 只要使用对应的数据库连接字符串即可. 而最近要迁移到新系统中,新系统使用.net core和EF Cor ...

  3. EF core 实现读写分离解决方案

    我们公司2019年web开发已迁移至.NET core,目前有部分平台随着用户量增加,单一数据库部署已经无法满足我们的业务需求,一直在寻找EF CORE读写分离解决方案,目前在各大技术论坛上还没找到很 ...

  4. 探寻ASP.NET MVC鲜为人知的奥秘(3):寻找多语言的最佳实践方式

    如果你的网站需要被世界各地的人访问,访问者会使用各种不同的语言和文字书写习惯,那么创建一个支持多语言的网站就是十分必要的了,这一篇文章就讲述怎么快速合理的创建网站对多语言的支持.接下来通过一个实例来讲 ...

  5. .NET Core调用WCF的最佳实践

    现在.NET Core貌似很火,与其他.NET开发者交流不说上几句.NET Core都感觉自己落伍了一样.但是冷静背后我们要也看到.NET Core目前还有太多不足,别的不多说,与自家的服务框架WCF ...

  6. React 代码共享最佳实践方式

    任何一个项目发展到一定复杂性的时候,必然会面临逻辑复用的问题.在React中实现逻辑复用通常有以下几种方式:Mixin.高阶组件(HOC).修饰器(decorator).Render Props.Ho ...

  7. Fibonacci(斐波那契数列)的最佳实践方式(JavaScript)

    1)低级版本 var fibonacci = function(n) { if (n == 0 || n == 1) { return n; } else { return fibonacci(n - ...

  8. Entity Framework Core 实现读写分离

    在之前的版本中我们可用构造函数实现,其实现在的版本也一样,之前来构造连接字符串,现在相似,构造DbContextOptions<T> 代码如下: public SContext(Maste ...

  9. SQL Server、MySQL主从搭建,EF Core读写分离代码实现

    一.SQL Server的主从复制搭建 1.1.SQL Server主从复制结构图 SQL Server的主从通过发布订阅来实现 1.2.基于SQL Server2016实现主从 新建一个主库&quo ...

随机推荐

  1. Ons 让人欲哭无泪问题,官方介绍不详

      订阅不一致导致消费时成功时失败问题: Console下使用.Net SDK 访问队列成功. Windows 服务下使用.Net SDK 访问队列成功.   有时成功,有时则没有任何反应-   解决 ...

  2. 微信小程序如何像vue一样在动态绑定类名

    微信小程序如何像vue一样在动态绑定类名 更新时间:2018年04月17日 14:08:44   这篇文章主要介绍了微信小程序如何像vue一样在动态绑定类名,文中给大家提到了vue与微信小程序的区别, ...

  3. LDAP概念和原理介绍

    LDAP概念和原理介绍 相信对于许多的朋友来说,可能听说过LDAP,但是实际中对LDAP的了解和具体的原理可能还比较模糊,今天就从“什么是LDAP”.“LDAP的主要产品”.“LDAP的基本模型”.“ ...

  4. VS2013 百度云资源以及密钥

    https://pan.baidu.com/s/1eu3XycWO8fWItmkFeYNv9w提取码:dy9r 密钥:BWG7X-J98B3-W34RT-33B3R-JVYW9 vs2015 http ...

  5. C/C++性能测试工具GNU gprof

    代码剖析(Code profiling)程序员在优化软件性能时要注意应尽量优化软件中被频繁调用的部分,这样才能对程序进行有效优化.使用真实的数据,精确的分析应用程序在时间上的花费的行为就成为_代码剖析 ...

  6. 利用 vue-cli 构建一个 Vue 项目

    一.项目初始构建 现在如果要构建一个 Vue 的项目,最方便的方式,莫过于使用官方的 vue-cli . 首先,咱们先来全局安装 vue-cli ,打开命令行工具,输入以下命令: $ npm inst ...

  7. 从零开始学习PYTHON3讲义(九)字典类型和插入排序

    <从零开始PYTHON3>第九讲 第六讲.上一讲我们都介绍了列表类型.列表类型是编程中最常用的一种类型,但也有挺明显的缺陷,比如: data = [5,22,34,12,87,67,3,4 ...

  8. Asp.Net Core 轻松学-HttpClient的演进和避坑

    前言     在 Asp.Net Core 1.0 时代,由于设计上的问题, HttpClient 给开发者带来了无尽的困扰,用 Asp.Net Core 开发团队的话来说就是:我们注意到,HttpC ...

  9. SmartSql Zookeeper分布式配置

    安装 SmartSql.ZooKeeperConfig Install-Package SmartSql.ZooKeeperConfig Demo string connStr = "192 ...

  10. jquery快速入门(一)

    一.jquery加载文档 jquery加载文档(也叫入口函数) $(document).ready(function(){ // 这里写 jQuery 代码... }); 简写方式: $(functi ...