【EFCore】.NET Core + EFCore 实现数据读写分离

EFCore 专栏收录该内容
6 篇文章 1 订阅

目录

介绍

为什么要读写分离?

如何实现读写分离?

为什么一个主库多个从库?

是否有缺点?

如何解决延迟问题?

具体如何实现?

实现

SqlServer 实现

.NET Core MVC项目实现

Models层实现


 

如今,我们操作数据库一般用ORM框架

现在用.NET Core + EFCore + SqlServer 实现数据读写分离

介绍

为什么要读写分离?

降低数据库服务器的压力

 

如何实现读写分离?

1.一个主库多个从库

2.配置主库复制数据到从库

 

 

为什么一个主库多个从库?

一般查询多于增删改,这就是我们常说的二八原则,20%操作是增删改,80%操作是查询

 

是否有缺点?

有延迟

 

如何解决延迟问题?

比较及时性的数据还是通过主库查询

 

具体如何实现?

通过发布服务器,主库发布,而从库订阅,从而实现主从库

实现

SqlServer 实现

使用SqlServer 2019,新建一个主库,创建表,再通过本地发布创建发布,

然后通过本地订阅订阅主库,创建两个从库

.NET Core MVC项目实现

项目结构

首先,在appsettings.json配置数据库连接字符串

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "EFCoreTestToRead": "Server=GREAMBWANG-DC\\MSSQLSERVER2019;Database=EFCoreTestToRead01;Trusted_Connection=True;,Server=GREAMBWANG-DC\\MSSQLSERVER2019;Database=EFCoreTestToRead02;Trusted_Connection=True;",
    "EFCoreTestToWrite": "Server=GREAMBWANG-DC\\MSSQLSERVER2019;Database=EFCoreTest;Trusted_Connection=True;"
  }
}

Models层实现

创建模型

public class UserInfo
{
    [Key]
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }

}

创建上下文

public class EFCoreContext : DbContext
{
    public EFCoreContext(string connectionString)
    {
        ConnectionString = connectionString;

        //创建数据库
        //Database.EnsureCreated();
    }

    private string ConnectionString { get; }

    public DbSet<UserInfo> UserInfo { get; set; }

    /// <summary>
    /// 配置连接数据库
    /// </summary>
    /// <param name="optionsBuilder"></param>
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        //base.OnConfiguring(optionsBuilder);
        optionsBuilder.UseSqlServer(ConnectionString);

    
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //base.OnModelCreating(modelBuilder); 
        
        //初始化数据
        modelBuilder.Entity<UserInfo>().HasData(new List<UserInfo>()
        {
            new UserInfo() { Id = 1, Name = "哈哈", Age = 17 },
            new UserInfo() { Id = 2, Name = "呵呵", Age = 18 },
            new UserInfo() { Id = 3, Name = "嘻嘻", Age = 19 }
        });
    }
}

创建上下文工厂

读写枚举

public enum WriteAndReadEnum
{
    Write,
    Read
} 

接口

public interface IDbContextFactory
{
    EFCoreContext CreateContext(WriteAndReadEnum writeAndRead);
}

实现

在实现数据查询上,可以使用不同的策略,一般有随机策略,权重策略,轮询策略

随机策略:随机选择一个从库进行查询

权重策略:根据权重比例选择从库查询

轮询策略:根据顺序选择从库查询

public class DbContextFactory : IDbContextFactory
{
    private IConfiguration Configuration { get; }
    private string[] ReadConnectionStrings;
    public DbContextFactory(IConfiguration configuration)
    {
        Configuration = configuration;
        ReadConnectionStrings = Configuration.GetConnectionString("EFCoreTestToRead").Split(",");
    }

    public EFCoreContext CreateContext(WriteAndReadEnum writeAndRead)
    {
        string connectionString = string.Empty;
        switch (writeAndRead)
        {
            case WriteAndReadEnum.Write:
                connectionString = Configuration.GetConnectionString("EFCoreTestToWrite");
                break;
            case WriteAndReadEnum.Read:
                connectionString = GetReadConnectionString();
                break;
            default:
                break;
        }
        return new EFCoreContext(connectionString);
    }

    private string GetReadConnectionString()
    {
        /*
         * 随机策略
         * 权重策略
         * 轮询策略
         */

        //随机策略
        string connectionString = ReadConnectionStrings[new Random().Next(0, ReadConnectionStrings.Length)];

        return connectionString;
    }
}

Models层完成

 

在Web层中

在Startup的ConfigureServices方法添加依赖注入

services.AddScoped<IDbContextFactory, DbContextFactory>();

操作

public class HomeController : Controller
{
    private readonly ILogger<HomeController> _logger;

    public IDbContextFactory DbContextFactory { get; }

    public HomeController(ILogger<HomeController> logger,IDbContextFactory dbContextFactory)
    {
        _logger = logger;
        DbContextFactory = dbContextFactory;
    }

    public IActionResult Index()
    {
        //写入操作
        EFCoreContext writeContext = DbContextFactory.CreateContext(WriteAndReadEnum.Write);
        writeContext.UserInfo.Add(new UserInfo() { Name = "AA", Age = 20 });
        writeContext.SaveChanges();

        //查询操作
        EFCoreContext readContext = DbContextFactory.CreateContext(WriteAndReadEnum.Read);
        UserInfo userInfo = readContext.UserInfo.OrderByDescending(u => u.Id).FirstOrDefault();

        return View();
    }
}

 

TO BE CONTINUED

 

 

 

 

  • 1
    点赞
  • 0
    评论
  • 2
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值