(精华)2020年7月15日 ASP.NET Core EFCore分库分表框架的使用(手写版)

举报
愚公搬代码 发表于 2021/10/19 00:00:05 2021/10/19
【摘要】 public void ConfigureServices(IServiceCollection services) { services.AddEFCoreSharding(config =&g...
public void ConfigureServices(IServiceCollection services)
{
    services.AddEFCoreSharding(config =>
    {
        单表
        //config.UseDatabase(Config.CONSTRING1, DatabaseType.SqlServer);
        使用多个数据库
        //config.UseDatabase<IMyDbAccessor>(Config.CONSTRING1, DatabaseType.SqlServer);

        //DateTime startTime = DateTime.Now.AddMinutes(-5);
        //DateTime endTime = DateTime.MaxValue;
        分表
        //config.AddAbsDb(DatabaseType.SqlServer)//添加抽象数据库
        //    .AddPhysicDbGroup()//添加物理数据库组
        //    .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.CONSTRING1)//添加物理数据库1
        //    .SetDateShardingRule<Base_UnitTest>(nameof(Base_UnitTest.CreateTime))//设置分表规则
        //    .AutoExpandByDate<Base_UnitTest>(//设置为按时间自动分表
        //        ExpandByDateMode.PerMinute,
        //        (startTime, endTime, ShardingConfig.DefaultDbGourpName)
        //        );
        //获取配置文件的连接字符串
        string conName = Configuration["ConnectionName"];
        //判断是否启用逻辑删除
        if (Configuration["LogicDelete"].ToBool())
            config.UseLogicDelete();
        //连接数据库
        config.UseDatabase(Configuration.GetConnectionString(conName), Configuration["DatabaseType"].ToEnum<DatabaseType>());
        //设置启用程序集的名称
        config.SetEntityAssembly(GlobalData.FXASSEMBLY_PATTERN);
    });
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

appsettings.json

{
  "LogicDelete": false, //是否开启逻辑删除,默认为物理删除
  "DatabaseType": "SqlServer", //默认数据库类型,定义详见EFCore.Sharding.DatabaseType
  "ConnectionName": "BaseDb", //默认连接字符串名
  "ConnectionStrings": {
    //SQLServer
    "BaseDb": "Data Source=.;Initial Catalog=Colder.Admin.AntdVue;Integrated Security=True;Pooling=true;"
    //PostgreSQL
    //"BaseDb": "SERVER=localhost;PORT=5432;DATABASE=Colder.Admin.AntdVue;USER ID=postgres;PASSWORD=postgres"
    //MySQl
    //"BaseDb": "server=127.0.0.1;user id=root;password=root;persistsecurityinfo=True;database=Colder.Admin.AntdVue;SslMode=none"
    //Oracle
    //"BaseDb": "Data Source=127.0.0.1/ORCL;User ID=COLDER.ADMIN.ANTDVUE;Password=123456;Connect Timeout=3"
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

普通的使用方式

ShardingConfig.Init(config =>
{
    config.AddAbsDb(DatabaseType.SQLite)
        .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, "DataSource=db.db")
        .AddPhysicDbGroup()
        .SetHashModShardingRule<Base_UnitTest>(nameof(Base_UnitTest.Id), 3);
});

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
using(IShardingDbAccessor _db = DbFactory.GetShardingDbAccessor())
{
	Base_UnitTest _newData  = new Base_UnitTest
	{
	    Id = Guid.NewGuid().ToString(),
	    UserId = "Admin",
	    UserName = "超级管理员",
	    Age = 22
	};
	List<Base_UnitTest> _insertList = new List<Base_UnitTest>
	{
	    new Base_UnitTest
	    {
	        Id = Guid.NewGuid().ToString(),
	        UserId = "Admin1",
	        UserName = "超级管理员1",
	        Age = 22
	    },
	    new Base_UnitTest
	    {
	        Id = Guid.NewGuid().ToString(),
	        UserId = "Admin2",
	        UserName = "超级管理员2",
	        Age = 22
	    }
	};
	//添加单条数据
	_db.Insert(_newData);
	//添加多条数据
	_db.Insert(_insertList);
	//清空表
	_db.DeleteAll<Base_UnitTest>();
	//删除单条数据
	_db.Delete(_newData);
	//删除多条数据
	_db.Delete(_insertList);
	//删除指定数据
	_db.Delete<Base_UnitTest>(x => x.UserId == "Admin2");
	//更新单条数据
	_db.Update(_newData);
	//更新多条数据
	_db.Update(_insertList);
	//更新单条数据指定属性
	_db.UpdateAny(_newData, new List<string> { "UserName", "Age" });
	//更新多条数据指定属性
	_db.UpdateAny(_insertList, new List<string> { "UserName", "Age" });
	//更新指定条件数据
	_db.UpdateWhere<Base_UnitTest>(x => x.UserId == "Admin", x =>
	{
	    x.UserId = "Admin2";
	});
	//GetList获取表的所有数据
	var list=_db.GetList<Base_UnitTest>();
	//GetIQPagination获取分页后的数据
	var list=_db.GetIShardingQueryable<Base_UnitTest>().GetPagination(pagination);
	//Max
	var max=_db.GetIShardingQueryable<Base_UnitTest>().Max(x => x.Age);
	//Min
	var min=_db.GetIShardingQueryable<Base_UnitTest>().Min(x => x.Age);
	//Average
	var min=_db.GetIShardingQueryable<Base_UnitTest>().Average(x => x.Age);
	//Count
	var min=_db.GetIShardingQueryable<Base_UnitTest>().Count();
	//事务,使用方式与普通事务一致
	bool succcess = _db.RunTransaction(() =>
	{
	    _db.Insert(_newData);
	    var newData2 = _newData.DeepClone();
	    _db.Insert(newData2);
	}).Success;
	Assert.AreEqual(succcess, false);
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

按时间分表

var db = DbFactory.GetShardingDbAccessor();
while (true)
{
    try
    {
        db.Insert(new Base_UnitTest
        {
            Id = Guid.NewGuid().ToString(),
            Age = 1,
            UserName = Guid.NewGuid().ToString(),
            CreateTime = DateTime.Now
        });

        DateTime time = DateTime.Now.AddMinutes(-2);
        var count = db.GetIShardingQueryable<Base_UnitTest>()
            .Where(x => x.CreateTime >= time)
            .Count();
        Console.WriteLine($"当前数据量:{count}");
        
        Stopwatch watch = new Stopwatch();
        var q = db.GetIQueryable<Base_UnitTest>()
            .Where(x => x.UserName.Contains("00001C22-8DD2-4D47-B500-407554B099AB"))
            .OrderByDescending(x => x.Id)
            .Skip(0)
            .Take(30);
        q.ToList();
        q.ToSharding().ToList();
        watch.Restart();
        var list1 = q.ToList();
        watch.Stop();
        Console.WriteLine($"未分表耗时:{watch.ElapsedMilliseconds}ms");//7800ms
        watch.Restart();
        var list2 = q.ToSharding().ToList();
        watch.Stop();
        Console.WriteLine($"分表后耗时:{watch.ElapsedMilliseconds}ms");//2400ms
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }

    Thread.Sleep(50);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

备注

/// <summary>
/// 单元测试表
/// </summary>
[Table("Base_UnitTest")]
[Index(false, nameof(CreateTime))]//建表自动创建索引
[Index(false, nameof(Age))]//建表自动创建索引
[Keys(nameof(Id), nameof(UserName))]//自动建表时会自动创建主键(多主键支持)
public class Base_UnitTest
{
    /// <summary>
    /// 代理主键
    /// </summary>
    [Key, StringLength(50)]
    public String Id { get; set; }

    /// <summary>
    /// 创建时间
    /// </summary>
    public DateTime CreateTime { get; set; }

    /// <summary>
    /// 用户名
    /// </summary>
    public String UserName { get; set; }

    /// <summary>
    /// Age
    /// </summary>
    public Int32? Age { get; set; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

多数据库插入

class Program
    {
        static void Main(string[] args)
        {
            Host.CreateDefaultBuilder(args)
                .ConfigureLogging(config =>
                {

                })
                .ConfigureServices((host, services) =>
                {
                    services.AddHostedService<DbTest>();
                    services.UseEFCoreSharding(config =>
                    {
                        //单表
                        config.UseDatabase(Config.CONSTRING1, DatabaseType.SqlServer);
                        //使用多个数据库
                        config.UseDatabase<IMyDbAccessor>(Config.CONSTRING1, DatabaseType.SqlServer);

                        DateTime startTime = DateTime.Now.AddMinutes(-5);
                        DateTime endTime = DateTime.MaxValue;
                        //分表
                        config.AddAbsDb(DatabaseType.SqlServer)//添加抽象数据库
                            .AddPhysicDbGroup()//添加物理数据库组
                            .AddPhysicDb(ReadWriteType.Read | ReadWriteType.Write, Config.CONSTRING1)//添加物理数据库1
                            .SetDateShardingRule<Base_UnitTest>(nameof(Base_UnitTest.CreateTime))//设置分表规则
                            .AutoExpandByDate<Base_UnitTest>(//设置为按时间自动分表
                                ExpandByDateMode.PerMinute,
                                (startTime, endTime, ShardingConfig.DefaultDbGourpName)
                                );
                    });
                })
                .Build()
                .Run();
        }
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
public interface IMyDbAccessor : IDbAccessor
    {

    }

  
 
  • 1
  • 2
  • 3
  • 4
class DbTest : BackgroundService
    {
        readonly IServiceProvider _serviceProvider;
        readonly ILogger _logger;
        public DbTest(IServiceProvider serviceProvider, ILogger<DbTest> logger)
        {
            _serviceProvider = serviceProvider;
            _logger = logger;
        }
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            Task.Factory.StartNew(async () =>
            {
                while (true)
                {
                    try
                    {
                        using (var scop = _serviceProvider.CreateScope())
                        {
                            //单表
                            var db = scop.ServiceProvider.GetService<IMyDbAccessor>();
                            List<Base_UnitTest> insertList = new List<Base_UnitTest>();
                            for (int i = 0; i < 100; i++)
                            {
                                insertList.Add(new Base_UnitTest
                                {
                                    Id = Guid.NewGuid().ToString(),
                                    Age = i,
                                    CreateTime = DateTime.Now,
                                    UserName = Guid.NewGuid().ToString()
                                });
                            }

                            var single = new Base_UnitTest
                            {
                                Id = Guid.NewGuid().ToString(),
                                Age = 100,
                                CreateTime = DateTime.Now,
                                UserName = Guid.NewGuid().ToString()
                            };

                            await db.InsertAsync(single);
                            await db.InsertAsync(insertList);

                            int count = await db.GetIQueryable<Base_UnitTest>().CountAsync();
                            _logger.LogInformation("单表插入数据成功 当前数据量:{Count}", count);

                            //分表
                            var shardingDb = scop.ServiceProvider.GetService<IShardingDbAccessor>();
                            await shardingDb.InsertAsync(single);
                            await shardingDb.InsertAsync(insertList);
                            count = await shardingDb.GetIShardingQueryable<Base_UnitTest>().CountAsync();
                            _logger.LogInformation("分表插入数据成功 当前数据量:{Count}", count);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "");
                    }

                    await Task.Delay(2000);
                }

            }, TaskCreationOptions.LongRunning);

            await Task.CompletedTask;
        }
    }

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

webapi的使用

[ApiController]
[Route("[controller]")]
public class TestController : ControllerBase
{
    readonly IShardingDbAccessor _shardingDbAccessor;
    public TestController(IShardingDbAccessor shardingDbAccessor)
    {
        _shardingDbAccessor = shardingDbAccessor;
    }

    [HttpGet]
    public async Task<string> Get()
    {
        List<Base_UnitTest> insertList = new List<Base_UnitTest>();
        for (int i = 0; i < 100; i++)
        {
            insertList.Add(new Base_UnitTest
            {
                Id = Guid.NewGuid().ToString(),
                Age = i,
                CreateTime = DateTime.Now,
                UserName = Guid.NewGuid().ToString()
            });
        }

        await _shardingDbAccessor.InsertAsync(insertList);

        return "成功";
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

备注:非分表用IDbAccessor,分表用IShardingDbAccessor

文章来源: codeboy.blog.csdn.net,作者:愚公搬代码,版权归原作者所有,如需转载,请联系作者。

原文链接:codeboy.blog.csdn.net/article/details/107110193

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。