企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 | 简单的分库分表设计

   2023-02-08 学习力0
核心提示:教程01 |模块化方案一02 |模块化方案二分库分表项目实战教程https://github.com/MrChuJiu/EasyLogger01 |前言02 |简单的分库分表设计03 |控制反转搭配简单业务04 |强化设计方案05 |完善业务自动创建数据库06 |最终篇-通过AOP自动连接数据库-完成日志业务前言

教程

01 | 模块化方案一

02 | 模块化方案二

分库分表项目实战教程

https://github.com/MrChuJiu/EasyLogger

01 | 前言

02 | 简单的分库分表设计

03 | 控制反转搭配简单业务

04 | 强化设计方案

05 | 完善业务自动创建数据库

06 | 最终篇-通过AOP自动连接数据库-完成日志业务

前言

项目涉及到了一些设计模式,如果你看的不是很明白,没有关系坚持下来,写完之后去思考去品,你就会有一种突拨开云雾的感觉,所以请不要在半途感觉自己看不懂选择放弃,如果我哪里写的详细,或者需要修正请联系我,谢谢。

创建项目

1.SDK安装

我们开发用的vs版本是2019 .Net Core的版本是3.1
下载 SDK 地址 :https://dotnet.microsoft.com/download

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

2.新建项目

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

这里选择Core 版本是3.1 项目类型是API
Docker支持我们不勾选,我会在后续给大家单独再开一个系列 我们专讲,慢慢来。

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

这里可以看到一个非常干净的项目就创建出来了,项目结构就是这样,里面的详情可以去看老张的第二个章节,讲的很明白,我就不在重复了
https://www.cnblogs.com/laozhang-is-phi/p/9495620.html
进阶可以去看开源源码 https://github.com/aspnet/MetaPackages/tree/master/src/Microsoft.AspNetCore
然后我们直接F5 启动项目看看 是不是新建的项目是不是没有问题,项目一切正常,我们开始进入正轨。

项目思考

1.分表

分表这个功能,就是把相同结构不同名称的多张表数据读取出来,这个部分其实很简单,我们常见的ORM都支持切换表名进行查询。

2.分库

分库如何实现呢。
先来看一下我们常用的ORM框架是如何连接数据库的。

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计 SqlSugar连接数据库

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计 FreeSql连接数据库

它们有一个共同点,NEW一个对象传递数据库连接字符串,设置好数据库类型,各自的xxx配置,就会得到一个连接的Client,然后就可以进行CRUD了。

那New多个对象,每个对象都是不同的连接字符串岂不是就可以操作多个数据库了。

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

大家写代码可别直接在业务/数据访问层这么写,整不好就让你下班领盒饭了。

那么这种情境下因该如何设计能让代码更加规范、易扩展呢!

3.思考

思路就是这样,那么如果让你来设计,你会怎么做呢,大家可以自己尝试着先去根据自己想法设计看看,然后我们下一节,我来给讲解我的设计方案。

设计要求

为了提高难度设计难度我们来同时兼容FreeSql、SqlSugar2款现在最热门的ORM。
我们设计要做到:

易扩展(就算再来一个我也能轻松支持)

切换快(不改动业务代码前提下,2个ORM框架我想用谁就用谁,随便切换)

可共存(可以取2款ORM各自优点在一起开发使用)

实战

1.制定规范

①、我们先新建一个类库 EasyLogger.DbStorage(ps:该类库用于制定规范,提供接口)

②、新建 Interface 文件夹

③、新建泛型接口 IAnyStorage (存储器)

该接口规范字典操作标准方法。
这里使用的ConcurrentDictionary 是一个并发字典。

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

 public interface IAnyStorage<T>
        where T : class
    {
        ConcurrentDictionary<string, T> DataMap { get; }

        T GetByName(string name, string defaultName);


        void AddOrUpdate(string name, T val);


        void Remove(string name);


        void Clear();
    }

2.遵循规范

我们先做SqlSugar的版本

①、新建 EasyLogger.SqlSugarDbStorage类库

②、新建 Interface 文件夹

③、新建 ISqlSugarProviderStorage (SqlSugar连接提供程序存储器) 接口继承IAnyStorage

继承IAnyStorage因为他是泛型继承它,我们需要传递一个参数,他是什么呢?当然是我们的SqlSugar连接提供程序了。

我们安装NuGet包安装 sqlSugarCore

⑤、新建ISqlSugarProvider (SqlSugar连接提供程序) 接口作为泛型参数传入

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

⑥、新建Impl 文件夹

⑦、新建 DefaultSqlSugarProviderStorage类继承 ISqlSugarProviderStorage 进行SqlSugar连接提供程序存储器的具体实现

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

public class DefaultSqlSugarProviderStorage : ISqlSugarProviderStorage
    {
        public ConcurrentDictionary<string, ISqlSugarProvider> DataMap { get; private set; }

        public DefaultSqlSugarProviderStorage(IServiceProvider serviceProvider)
        {
            DataMap = new ConcurrentDictionary<string, ISqlSugarProvider>();

            var tmpDataMap = serviceProvider.GetServices<ISqlSugarProvider>()
                .ToDictionary(item => item.ProviderName);

            foreach (var item in tmpDataMap)
            {
                this.AddOrUpdate(item.Key, item.Value);
            }
        }
        public void AddOrUpdate(string name, ISqlSugarProvider val)
        {
            DataMap[name] = val;
        }

        public void Clear()
        {
            DataMap.Clear();
        }

        public ISqlSugarProvider GetByName(string name, string defaultName)
        {
            ISqlSugarProvider result = null;

            if (name == null)
            {
                if (!DataMap.TryGetValue(defaultName, out result))
                {
                    throw new Exception("没有找到 DefaultName Provider");
                }
                return result;
            }
            else if (DataMap.TryGetValue(name, out result))
            {
                return result;
            }

            throw new ArgumentException($"没有找到  {name}  Provider");
        }

        public void Remove(string name)
        {
            if (string.IsNullOrWhiteSpace(name))
            {
                return;
            }

            this.DataMap.TryRemove(name, out ISqlSugarProvider result);
        }
    }

字典的操作我想都能看明白,基础差的朋友可能会觉得不懂的就是下面这句,这是做什么呢,其实就是我们把注入ISqlSugarProvider的实现都查询
出来,放到我们的DateMap集合中(好处后面我会实践给大家讲到),到此我们SqlSugar连接提供程序存储库就完成了。

     var tmpDataMap = serviceProvider.GetServices<ISqlSugarProvider>()
                .ToDictionary(item => item.ProviderName);

            foreach (var item in tmpDataMap)
            {
                this.AddOrUpdate(item.Key, item.Value);
            }

差点SqlSugar连接提供程序的实现给漏了。
我们在 Impl 文件夹 新建 SqlSugarProvider类,继承ISqlSugarProvider接口。

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

public class SqlSugarProvider : ISqlSugarProvider
    {
        public string ProviderName { get; set; }
        public SqlSugarClient Sugar { get; set; }

        public SqlSugarProvider()
        {
            this.Sugar = this.CreateSqlSugar();
            this.ProviderName = "DefaultSqlSugar";
        }

        private SqlSugarClient CreateSqlSugar()
        {
            // todo 临时
            var db = new SqlSugarClient(
             new ConnectionConfig()
             {
                 ConnectionString = "server=.;uid=sa;pwd=@jhl85661501;database=SqlSugar4XTest",
                 DbType = DbType.SqlServer,//设置数据库类型
                IsAutoCloseConnection = true,//自动释放数据务,如果存在事务,在事务结束后释放
                InitKeyType = InitKeyType.Attribute //从实体特性中读取主键自增列信息
            });
            return db;
        }

        public void Dispose()
        {
            this.Sugar.Dispose();
        }
    }

CreateSqlSugar 方法是我从SqlSugar官方复制过来的,大家注意把ConnectionString改成自己的数据库连接。

我们现在来配置一下 Startup 先看看效果。

感谢 @Damn 帮我发现漏掉说明的代码!

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

 public void ConfigureServices(IServiceCollection services)
        {
            // 注入
            services.AddSingleton<ISqlSugarProvider, SqlSugarProvider>();
            services.AddSingleton<ISqlSugarProviderStorage, DefaultSqlSugarProviderStorage>();
            services.AddControllers();
        }

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

   app.Use(async (context, next) =>
            {
                var sqlStorage = app.ApplicationServices.GetService<ISqlSugarProviderStorage>();
                var sugarClient = sqlStorage.GetByName(null, "DefaultSqlSugar").Sugar;
                Console.WriteLine("查看sugarClient");
            });

我们成功的从SqlSugar连接提供程序存储中,拿到SqlSugarClient连接。

补充

下面代码是我在技术群里看到使用FreeSql的方式,这么写没有问题简单单例的实现,我推荐大家使用上文中依赖注入的方式来使用!

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

企业项目实战 .Net Core + Vue/Angular 分库分表日志系统二 |  简单的分库分表设计

结尾

回顾一下本节的内容。

1.我们新建统一的泛型 IAnyStorage接口(连接提供程序存储库)来规范调用。
2.我们创建了 ISqlSugarProviderStorage (SqlSugar连接提供程序存储库) 通过继承IAnyStorage来规范接口实现。
3.新建了 ISqlSugarProvider (SqlSugar连接提供程序).
4.我们完善了接口的实现。
5.我们成功在 Startup 中新建一个简单的中间件 成功从SqlSugar连接提供程序存储中,拿到SqlSugarClient连接。

思考问题

我们把数据库连接字符串写在(SqlSugar连接提供程序)合理吗,是不是依赖太深,这个时候我们就用到控制反转来降低依赖性,那么具体怎么做呢!

 
反对 0举报 0 评论 0
 

免责声明:本文仅代表作者个人观点,与乐学笔记(本网)无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
    本网站有部分内容均转载自其它媒体,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责,若因作品内容、知识产权、版权和其他问题,请及时提供相关证明等材料并与我们留言联系,本网站将在规定时间内给予删除等相关处理.

  • Angular.js的作用域和数据绑定
    初识Angular.js通过初识Angular.js可以做一个简单的入门,下面开始做深入的了解吧。作用域作用域($scope)和应用的数据模型相关联的,同时作用域也是表达式执行的上下文。$scope对象是定义应用业务逻辑、控制器方法和视图属性的地方。 作用域是视图和控制器
    03-16
  • Angular 4 设置组件样式的几种方式
    Angular 4 设置组件样式的几种方式
      你用Angular吗?一.介绍  如何只改动最简单的css代码,呈现完全不一样的视图效果。第一种:最基本的设置:  图1 代码 图2 界面运行效果图平常,想给一个label或者p等标签添加样式,我们就是这样操作,在Angular中也是一样的。现在,如果我想要将字体换
    03-16
  • angularJSapi学习-angular.copy使用
    angular.copy使用效果:初始状态:输入信息后未保存状态:点击save后状态:当输入框内容和master内容不一致时:点击reset使得user的信息被重置为master中信息: 具体代码: 1 !DOCTYPE HTML 2 html ng-app="app" 3 headscript src="./angular.min.js"/script
    03-16
  • Ionic启动时提示:The Angular CLI requires a minimum Node.js version of eithor v10.13 or v12.0
    Ionic启动时提示:The Angular CLI requires a m
    在新建ionic项目后通过ionic serve 启动ionic项目时提示:The Angular CLI requires a minimum Node.js version of eithor v10.13 or v12.0  注:博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号霸道的程序猿获取编程相关电子书、教程推送与
    03-16
  • Angular.js之内置过滤器学习笔记 javascript过
    !DOCTYPE htmlhtml lang="en"headmeta charset="UTF-8"titleangularFilter/titlescript src="http://cdn.bootcss.com/angular.js/1.4.6/angular.js"/script/head  body ng-app="angularJS" ng-controller="ctrl"    div{{
    03-08
  • Angular 隨記
    Windows下更新Node 和NPM方法管理員模式打開powershell執行以下命令:Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Forcenpm install -g npm-windows-upgradenpm-windows-upgrade
    03-08
  • 双向数据绑定(angular,vue) 双向数据绑定指令
    最近github上插件项目更新了关于双向数据绑定的实现方式,关于angular和vue.angular众所周知是使用的脏检查($dirty)。一开始大家会认为angular开启了类似setInterval去不停的循环检查,性能极差,但其实并不是,$dirty是在一定条件下才会去执行,比如输入框
    03-08
  • 六、angular 生成二维码
    六、angular 生成二维码
    首先需要安装angular-qrcode :bower install monospaced/angular-qrcodenpm install angular-qrcode如何使用?在相应的需要使用二维码的页面增加如下代码:注意:这里的“version”和"size"可以根据github上面找出自己想要的结果:生成含有图片的二维码:这里
    03-08
  • angular.js简单入门。 angular入门教程
    angular.js简单入门。 angular入门教程
    小弟刚接触angular js  就写了一个简单的入门。后续慢慢补。。。首先看 html 页面。htmlmeta charset="UTF-8"headtitleangularJS/title/headscript type="text/javascript" src="./js/angular.min.js"/script      //引入 angularJSscript type="text/
    03-08
点击排行