ORM框架对分表分库之分库和分表指定不同的字段

ORM框架分库分表已实现了

  1. 只分表(根据指定字段)
    点我查看demo
  2. 只分库(根据指定字段)
    点我查看demo
  3. 既分库又分表(根据相同的字段)
    点我查看demo

上面几点之前我在博客中已经写了使用介绍,点我查看

最近我完善了分库分表功能:

分库和分表可以指定不同的字段

首先看下配置上是如何配置的

image

在配置上相比于上面提到的第3点,配置文件新增了

  • dbcolumn 代表db是根据哪个字段分
  • column 代表的table是根据哪个字段分
 {
      "Provider": "mysql",
      "Name": "testshardingdbandtableMany",
      "ShardingStrategy": "class=AntData.DbEngine.Sharding.ModShardingStrategy;dbcolumn=CityId;column=ID;mod=3;shardByDB=true;shardByTable=true",
      "ConnectionItemList": [
        {
          "Name": "testorm_mysql0",
          "Sharding": "0",
          "ConnectionString": "Server=127.0.0.1;Port=3306;Database=testorm1;Uid=root;Pwd=123456;charset=utf8;SslMode=none",
          "DatabaseType": "Master"
        },
        {
          "Name": "testorm_mysql1",
          "Sharding": "1",
          "ConnectionString": "Server=127.0.0.1;Port=3306;Database=testorm2;Uid=root;Pwd=123456;charset=utf8;SslMode=none",
          "DatabaseType": "Master"
        }
      ]

    }

根据上面的配置的意思就是:

  1. class=AntData.DbEngine.Sharding.ModShardingStrategy代表的是按照取模策略来分表分库
  2. shardByDB=true;shardByTable=true 开启了分库分表的开关
  3. dbcolumn=CityId 代表的是分库是按照CityId的来分
  4. column=ID;代表的是分表是按照ID的值字段来分
  5. mod=3;代表的分表是按照3来取模
  6. db的取模是看ConnectionItemList有配置几个,上面的例子是配置2个,所以分库是按照2来取模

对应我的库和表如下

image

image

根据codegen来生成代码

注意一点:
代码生成器生成的表需要自己加一个_{0}
例如:[Table(Comment = "订单表", Name = "order_{0}")]

    /// <summary>
    /// Database       : testorm1
    /// Data Source    : localhost
    /// Server Version : 5.6.26-log
    /// </summary>
    public partial class Entitys : IEntity
    {
        /// <summary>
        /// 订单表
        /// </summary>
        public IQueryable<Order> Orders { get { return this.Get<Order>(); } }

        private readonly IDataContext con;

        public IQueryable<T> Get<T>()
            where T : class
        {
            return this.con.GetTable<T>();
        }

        public Entitys(IDataContext con)
        {
            this.con = con;
        }
    }

    /// <summary>
    /// 订单表
    /// </summary>
    [Table(Comment = "订单表", Name = "order_{0}")]
    public partial class Order : BaseEntity
    {
        #region Column

        /// <summary>
        /// 订单号
        /// </summary>
        [Column("ID", DataType = DataType.Int64, Comment = "订单号"), Nullable]
        public long? ID { get; set; } // bigint(20)

        /// <summary>
        /// 名称
        /// </summary>
        [Column("Name", DataType = DataType.VarChar, Length = 50, Comment = "名称"), Nullable]
        public string Name { get; set; } // varchar(50)


        /// <summary>
        /// CityId
        /// </summary>
        [Column("CityId", DataType = DataType.Int64, Comment = "CityId"), Nullable]
        public long CityId { get; set; } 

        #endregion
    }

下面来写测试代码验证



        /// <summary>
        /// 测试mod分库插入到testorm2数据库的order_1表
        /// </summary>
        [TestMethod]
        public void TestMethod6_01()
        {
            var id = 1;
            //查testorm2 的 order_1 表
            var odIsExist = DB.Tables.Orders.Any(r => r.ID.Equals(1) && r.CityId == 1);
            if (odIsExist)
            {
                return;
            }
            var order = new Order
            {
                ID = 1,//按照id分表
                Name = "上海大学",
                CityId = 1//按照cityid分库
            };

            var result = DB.Insert(order);
            Assert.AreEqual(result, 1);

        }

        /// <summary>
        /// 测试mod分库插入到testorm1数据库
        /// </summary>
        [TestMethod]
        public void TestMethod6_02()
        {

            var id = 2;
            //查testorm1 的 order_2 表
            var odIsExist = DB.Tables.Orders.Any(r => r.ID.Equals(2) && r.CityId == 2);
            if (odIsExist)
            {
                return;
            }
            var order = new Order
            {
                ID = 2,
                Name = "北京大学",
                CityId = 2
            };

            var result = DB.Insert(order);
            Assert.AreEqual(result, 1);
        }

        [TestMethod]
        public void TestMethod6_022()
        {

            var id = 2;
            //3%2=1 查testorm1 的3%3=0 order_0 表
            var odIsExist = DB.Tables.Orders.Any(r => r.ID.Equals(3) && r.CityId == 3);
            if (odIsExist)
            {
                return;
            }
            var order = new Order
            {
                ID = 3,
                Name = "厦门大学",
                CityId =3
            };

            var result = DB.Insert(order);
            Assert.AreEqual(result, 1);
        }

        /// <summary>
        /// 测试mod分库 查询testorm2数据库
        /// </summary>
        [TestMethod]
        public void TestMethod6_03()
        {
            var id = 1;
            // 1%2=1 testorm2的 1%3=1 order_1
            var tb1 = DB.Tables.Orders.FirstOrDefault(r => r.ID.Equals(1)&&r.CityId ==1);
            Assert.IsNotNull(tb1);
        }

        /// <summary>
        /// 测试mod分库 查询testorm1数据库
        /// </summary>
        [TestMethod]
        public void TestMethod6_04()
        {
            var id = 2;
            // 2%2=0 testorm1的 2%3=2 order_2
            var tb1 = DB.Tables.Orders.FirstOrDefault(r => r.ID.Equals(2)&&r.CityId ==2);
            Assert.IsNotNull(tb1);
        }

        /// <summary>
        /// 测试mod分库 不指定sharing column 查询叠加
        /// </summary>
        [TestMethod]
        public void TestMethod6_05()
        {
            //没有指定CityID也没有指定ID 会查询2个db的各3张表 6次的叠加
            var tb1 = DB.Tables.Orders.ToList();
            Assert.IsNotNull(tb1);
            Assert.AreEqual(tb1.Count, 3);
            //没有指定CityID 那么会查询2个db 。由于指定了ID 那么只会查询 1%3=1 order_1 2%3=2 order_2
            var odIsExist = DB.Tables.Orders.Where(r => r.ID.Equals(1) || r.ID.Equals(2)).ToList();
            Assert.AreEqual(odIsExist.Count, 2);
        }

        /// <summary>
        /// 测试mod分库修改到testorm2数据库
        /// </summary>
        [TestMethod]
        public void TestMethod6_06()
        {
            var id = 1;
            //没有指定CityID 那么会查询2个db 。由于指定了ID 那么只会查询 1%3=1 order_1 
            var result = DB.Tables.Orders.Where(r => r.ID.Equals(1)).Set(r => r.Name, y => y.Name + "1").Update();
            Assert.AreEqual(result, 1);
        }

        /// <summary>
        /// 测试mod分库修改到testorm1数据库
        /// </summary>
        [TestMethod]
        public void TestMethod6_07()
        {
            var id = 2;
            //没有指定CityID 那么会查询2个db 。由于指定了ID 那么只会查询 2%3=2 order_2 
            var result = DB.Tables.Orders.Where(r => r.ID.Equals(2)).Set(r => r.Name, y => y.Name + "1").Update();
            Assert.AreEqual(result, 1);
        }

        /// <summary>
        /// 测试mod分库删除到testorm2数据库
        /// </summary>
        [TestMethod]
        public void TestMethod6_08()
        {
            var id = 1;
            //没有指定CityID 那么会查询2个db 。由于指定了ID 那么只会查询 1%3=1 order_1 
            var result = DB.Tables.Orders.Where(r => r.ID.Equals(1)).Delete();
            Assert.AreEqual(result, 1);
        }

        /// <summary>
        /// 测试mod分库删除到testorm1数据库
        /// </summary>
        [TestMethod]
        public void TestMethod6_09()
        {
            var id = 2;
            //没有指定CityID 那么会查询2个db 。由于指定了ID 那么只会查询 2%3=2 order_2
            var result = DB.Tables.Orders.Where(r => r.ID.Equals(2)).Delete();
            Assert.AreEqual(result, 1);
        }

        /// <summary>
        /// 测试mod分库批量分别插入到testorm1 和 testorm2数据库
        /// </summary>
        [TestMethod]
        public void TestMethod7_02()
        {
            var orderList = new List<Order>();
            //会分到3%2=1 testorm2 的 order_0
            orderList.Add(new Order
            {
                ID = 3,
                Name = "上海大学",
                CityId = 3
            });
            //会分到4%2=0 testorm1 的 order_1
            orderList.Add(new Order
            {
                ID = 4,
                Name = "上海大学",
                CityId = 4
            });

            //没有指定 shading column的话是默认分到第一个分片
            orderList.Add(new Order
            {
                ID = null,
                Name = "上海大学",
                //CityId = 0
            });
             var rows = DB.BulkCopy(orderList);
            Assert.AreEqual(rows.RowsCopied, 3);
        }

        [TestMethod]
        public void TestMethod7_03()
        {
            var odIsExist = DB.Tables.Orders.Delete();

        }

        /// <summary>
        /// 指定了shadingtable的分库 自动会走到1对应的db
        /// </summary>
        [TestMethod]
        public void TestMethod7_04()
        {
            DB.UseShardingDbAndTable("1","1", con =>
            {
                //1%2 = 1 1%3 = 1 testorm2 的 order_1
                var first = con.Tables.Orders.FirstOrDefault();
                Assert.IsNotNull(first);
                Assert.AreEqual(1, first.ID);
            });

        }

        /// <summary>
        /// 指定了shadingtable的分库 自动会走到0对应的db
        /// </summary>
        [TestMethod]
        public void TestMethod7_05()
        {
            DB.UseShardingDbAndTable("0","0", con =>
            {
                //0%2 = 0 0%3 = 0 testorm1 的 order_0
                var first = con.Tables.Orders.FirstOrDefault();
                Assert.IsNotNull(first);
                Assert.AreEqual(2, first.ID);
            });

        }


总结

目前在AntData orm中使用分库分表在使用上是不是很爽:

  1. 决定好用哪种策略 是取模 还是区间分片
  2. 支持只分表,只分库,或者既分表又分库
  3. 如果既分表又分库还可以指定分库和分表的字段不同
  4. 只需要在配置文件上配置好即可
  5. 在写代码和平常一样

如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,转载文章之后须在文章页面明显位置给出作者和原文连接,谢谢。
原文地址:https://www.cnblogs.com/yudongdong/p/14409367.html