EF Ccore 主从配置 最简化
业务需要 配置一主多从数据库 读写分离 orm用的ef core , 把思路和代码写下
1. 配置2个数据库上下文 ETMasterContext ETSlaveContext(把增删改功能禁用掉)
public class ETMasterContext : DbContext
{
public ETMasterContext(DbContextOptions<ETMasterContext> options)
: base(options)
{}
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfiguration(new UserConfiguration());
}
}
public class ETSlaveContext : DbContext
{
public ETSlaveContext(DbContextOptions<ETSlaveContext> options)
: base(options)
{}
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);modelBuilder.ApplyConfiguration(new UserConfiguration());
}
public override int SaveChanges()
{
throw new InvalidOperationException("只读数据库,不允许写入");
}
public override int SaveChanges(bool acceptAllChangesOnSuccess)
{
throw new InvalidOperationException("只读数据库,不允许写入");
}
public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
{
throw new InvalidOperationException("只读数据库,不允许写入");
}
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
{
throw new InvalidOperationException("只读数据库,不允许写入");
}}
2. 定义2个Repository EfRepository(主) EfReadOnlyRepository(只读)
public class EfRepository<T> : IRepository<T> where T : EntityBase
{
protected readonly ETMasterContext Context;public EfRepository(ETMasterContext context)
{
Context = context;
//Context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}public IQueryable<T> Table => Context.Set<T>().AsQueryable();
public IQueryable<T> TableNoTracking => Context.Set<T>().AsNoTracking();
public int Delete(T entity)
{
try
{
Context.Set<T>().Remove(entity);
return 1;
}
catch (Exception)
{return 0;
}
}public int DeleteWhere(Expression<Func<T, bool>> criteria)
{
try
{
IQueryable<T> entities = Context.Set<T>().Where(criteria);
foreach (var entity in entities)
{
Context.Entry(entity).State = EntityState.Deleted;
}
return 1;
}
catch (Exception)
{
return 0;
}}
public T GetById(object id)
{
return Context.Set<T>().Find(id);
}public int Insert(T entity)
{
try
{
Context.Set<T>().Add(entity);
return 1;
}
catch (Exception ex)
{
return 0;
}}
public int InsertMany(IEnumerable<T> list)
{
try
{
Context.Set<T>().AddRange(list);
return 1;
}
catch (Exception ex)
{
return 0;
}
}public int Update(T entity)
{
try
{
Context.Entry(entity).State = EntityState.Modified;
return 1;
}
catch (Exception)
{
return 0;
}
}
}
public class EfReadOnlyRepository<T> : IReadOnlyRepository<T> where T : EntityBase
{
protected readonly ETSlaveContext Context;public EfReadOnlyRepository(ETSlaveContext context)
{
Context = context;
//Context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
}public IQueryable<T> Table => Context.Set<T>().AsQueryable();
public IQueryable<T> TableNoTracking => Context.Set<T>().AsNoTracking();
public T GetById(object id)
{
return Context.Set<T>().Find(id);
}
}
3. 用到的接口补上
public interface IReadOnlyRepository<T> where T : EntityBase
{
IQueryable<T> Table { get; }IQueryable<T> TableNoTracking { get; }
T GetById(object id);
}public interface IRepository<T> : IReadOnlyRepository<T> where T : EntityBase
{
int Insert(T entity);
int InsertMany(IEnumerable<T> list);
int Update(T entity);
int Delete(T entity);
int DeleteWhere(Expression<Func<T, bool>> criteria);
}
4. Startup ConfigureServices 中配置上下文
services.AddDbContext<ETMasterContext>(options =>
options.UseMySql(GetConnectionStringByRandom("MySql_Master")));
services.AddDbContext<ETSlaveContext>(options =>
options.UseMySql(GetConnectionStringByRandom("MySql_Slave")));
private string GetConnectionStringByRandom(string connectionString)
{
var connstr = Configuration.GetConnectionString(connectionString);
if (string.IsNullOrEmpty(connstr))
{
throw new Exception("数据库配置有误");
}var conList = connstr.Trim('|').Split('|');
var rand = new Random().Next(0, conList.Length);
return conList[rand];
}
5. appsetting.json 配置多个连接字符串 | 分隔
"connectionStrings": {
"MySql_Master": "server=192.168.87.169;database=poker_games;uid=root;pwd=1$=6yuan;SslMode=None;",
"MySql_Slave": "server=192.168.87.169;database=poker_games;uid=root;pwd=1$=6yuan;SslMode=None;|server=192.168.87.169;database=poker_games;uid=root;pwd=1$=6yuan;SslMode=None;"
}
6. 实际应用
public class ReportService : IReportService
{
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IDistributedCache _distributedCache;
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
private readonly IReadOnlyRepository<Bet> _betRepository;public ReportService(
IHttpContextAccessor httpContextAccessor,
IDistributedCache distributedCache,
IUnitOfWork unitOfWork,
IMapper mapper,
IReadOnlyRepository<Bet> betRepository
)
{
_httpContextAccessor = httpContextAccessor;
_distributedCache = distributedCache;
_unitOfWork = unitOfWork;
_mapper = mapper;
_betRepository = betRepository;
}}
public ReturnValue GetAgentBetReportByRound(AgentBetReportByRoundCriteriaModel reportModel)
{var betList = _betRepository.TableNoTracking.Where(p => p.pay_out_date >= beginTime && p.pay_out_date < endTime);
return new ReturnValue(betList );}
7. 大概解释下
如图 DBContext的生命周期默认是Scoped,即整个reqeust请求的生命周期以内共用了一个Context
利用这个生命周期 在每次请求时 通过配置文件获取不同的上下文实例 即实现了 多主多从 读写分离功能
EF Ccore 主从配置 最简化的更多相关文章
- mongodb3.x主从配置及备份
本文将介绍下mongodb主从配置及备份 MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在为 WEB 应用提供可扩展的高性能数据存储解决方案. MongoDB 是一个介于关 ...
- docker Redis的主从配置
redis是k-v型nosql数据库,支持字符串(string).列表(list).集合(set).散列(hash).有序集合(zset:形如member:score的散列集合,其中member为成员 ...
- CentO7 安装 redis, 主从配置,Sentinel集群故障转移切换
一.Redis的安装(前提是已经安装了EPEL) 安装redis: yum -y install redis 启动/停止/重启 Redis 启动服务: systemctl start re ...
- PostgreSQL9.6主从配置
参考文档: 备机日志传送:https://www.postgresql.org/docs/9.6/static/warm-standby.html 英文文档:https://www.postgresq ...
- MySQL主从配置详解
一.mysql主从原理 1. 基本介绍 MySQL 内建的复制功能是构建大型,高性能应用程序的基础.将 MySQL 的 数亿分布到到多个系统上去,这种分步的机制,是通过将 MySQL 的某一台主机的数 ...
- Redis学习总结(四)--Redis主从配置
在分布式系统架构设计中高可用是必须考虑的因素之一.高可用通常是指,通过设计减少系统不能提供服务的时间.而单点是系统高可用的最大的败笔,如果单点出现问题的话,那么整个服务就不能使用了,所以应该尽量在系统 ...
- mysql主从配置实现一主一从读写分离
主从介绍Mysql主从又叫Replication.AB复制.简单讲就是A与B两台机器做主从后,在A上写数据,另外一台B也会跟着写数据,实现数据实时同步mysql主从是基于binlog,主上需开启bin ...
- mysql主从配置
引言: 双11,阿里云服务器打折,于是我忍不住又买了一台服务器,于是咱也是有两台服务器的爷们了,既然有了两台服务器,那么肯定要好好利用一下吧,那么就来玩玩mysql的主从配置吧. 准备 两台数据库服务 ...
- postgresql pgsql最新版安装指南及数据存储路径更改及主从配置
postgresql pgsql最新版安装指南及数据存储路径更改及主从配置 安装指南 首先在apt的list添加你当前系统版本对应的apt列表 目前官网有16.04,14.04,12.04 分别对应下 ...
随机推荐
- (转)python编写登录接口
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://506554897.blog.51cto.com/2823970/1907262 ...
- Android NDK 安装与配置
本文主内容: 1. Android NDK 安装 2. 安装Cygwin与使用NDK编译 3. 在Eclipse中集成C/C++开发环境CDT 4. 安装Sequoyah插件 5. JNI编 ...
- C#(Winform)的Show()和ShowDialog()方法
1. 显示窗口的两种方式: Winform中的Form,在显示窗口时,可以使用Show()和ShowDialog()两种方式 2. 非模态窗口方式(可以跟其他界面自由切换,而且不阻塞代码) Show( ...
- jquery autocomplete jqueryui报错
使用jquery autocomplete 但是却报错jquery ui 0 TypeError: t[0] is undefined 本地部署是没有问题的,但是放到正式上面就会出错. 同时mvc的m ...
- Android4.4 在Framework新增内部资源编译不过的问题
如果在Frameworks新增内部资源,并在Java代码中使用类似形式来引用资源:com.android.internal.R.layout.xxx,需要在frameworks/base/core/r ...
- Spring课程 Spring入门篇 4-6 Spring bean装配之基于java的容器注解说明--@ImportResource和@Value java与properties文件交互
1 解析 1.1 这两个注解应用在什么地方 1.2 应用方式 1.3 xml方式实现取值 2 代码演练 2.1 @ImportResource和@Value代码演练 1 解析 1.1 这两个注解应用在 ...
- 记升级一次的http2学习
首先,就先对比下http2和http1.X的区别和升级它的优势吧. 在 HTTP .X 中,为了性能考虑,我们会引入雪碧图.将小图内联.使用多个域名等等的方式.这一切都是因为浏览器限制了同一个域名下的 ...
- Scarpy框架持久化存储
一.介绍 持久化存储操作分为两类:磁盘文件和数据库. 而磁盘文件存储方式又分为:基于终端指令和基于管道 二.基于终端指令的持久化存储 Scrapy是通过 scrapy 命令行工具进行控制的. 这里我们 ...
- ECMAScript 6简介
一.起步 1.扎实的HTML/CSS/Javascript基本功,这是前置条件. 2.不要用任何的构建项目工具,只用最简单的<script>,把教程里的例子模仿一遍,理解用法.不推荐上来就 ...
- 【代码笔记】Java文件的输入输出(1)——Java.io包的初步理解
Java里面文件的输入输出全部在java.io包里面. Java.io包里面所有的类都需要掌握. java.io包里面所有的东西都在上面了. 包里面的相关类.异常等树关系如下 类分层结构 java.l ...