自定义分表 用例 xxxx_202201 格式 返回

SqlSugar 老数据
13 5030

说明

自带的时间分表相当完善,但是有些用户就是不想要这种格式 xxx_20220101 ,他想要 xxx_202201 这样的,那我们就用自定义分表实现


1、创建自定义服务

public class yyyyMMService : ISplitTableService
        {
            public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
            {
                List<SplitTableInfo> result = new List<SplitTableInfo>();
                foreach (var item in tableInfos)
                {
                    var tableName = EntityInfo.DbTableName.Replace("_{yyyyMM}","");
                    if (EntityInfo.DbTableName.Contains("_{yyyyMM}") &&item.Name.Contains(tableName))// MySpliteTest_202204  这种格式的表
                    {
                        SplitTableInfo tableInfo = new SplitTableInfo();
                        tableInfo.TableName =item.Name;
                        var value = Regex.Match(item.Name, @"\d{6}$").Value;
                        if(value!=null)
                        {
                        value=value.Insert(4, "-");
                        tableInfo.Date = Convert.ToDateTime(value + "-01");
                        //tableInfo.String = null;  Time table, it doesn't work
                        //tableInfo.Long = null;  Time table, it doesn't work
                        result.Add(tableInfo);
                        }
                    }
                }
                return result;
            }

            public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
            {
                var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
                if (splitColumn == null)
                {
                    return db.GetDate();
                }
                else
                {
                    var value = splitColumn.PropertyInfo.GetValue(entityValue, null);
                    return value;
                }
            }

            public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
            {
                return EntityInfo.DbTableName.Replace("{yyyyMM}", DateTime.Now.ToString("yyyyMM")) ;
            }

            public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type)
            {
                return EntityInfo.DbTableName.Replace("{yyyyMM}", DateTime.Now.ToString("yyyyMM"));
            }

            public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
            {
                return entityInfo.DbTableName.Replace("{yyyyMM}",Convert.ToDateTime(fieldValue).ToString("yyyyMM"));
            }
        }

2、创建实体类

分表字段和实体特性要写正确

    [SplitTable(SplitType.Month)]//标识只按月,可以用自带分表的功能
    [SugarTable("MySpliteTest_{yyyyMM}")]//格式
    public class MySpliteTest 
    {
        [SugarColumn(IsPrimaryKey = true)]
        public Guid Pk { get; set; }

        public string  Name { get; set; }

        [SplitField]//分表字段
        public DateTime Time { get; set; }
    }

3、使用自定义分表

有2种方式,高版本可以用特性定义自定义分表

    //配置方式1: 
    //CurrentConnectionConfig里面需要配一下自定义分表服务
    db.CurrentConnectionConfig.ConfigureExternalServices = new ConfigureExternalServices
    {
       SplitTableService=new yyyyMMService()
    }; 
    
    //配置方式2:高版本支持了特性使用自定义分表 5.1.4.78
     [SplitTable(SplitType._Custom01,typeof(yyyyMMService))]
     
    
    
    //同步结构
    db.CodeFirst.SplitTables().InitTables<MySpliteTest>();
    
    //插入查询和自带的时间分表一样
    db.Insertable(new MySpliteTest() { Name = "a", Time = DateTime.Now }).SplitTable().ExecuteCommand();
    db.Queryable<MySpliteTest>().SplitTable(DateTime.Now.AddDays(-1000), DateTime.Now).ToList();
    Console.WriteLine("#### CodeFirst end ####");


热忱回答13

  • fate sta fate sta VIP0
    2022/5/30

    欢迎大家分享更多自已的分表

    0 回复
  • landon landon VIP0
    2022/6/16

    代码在执行到

     value=value.Insert(4, "-");

    的时候报错了

    0 回复
  • fate sta fate sta VIP0
    2022/6/16

    那就是你的数据库表名取的不对

    0 回复
  • fate sta fate sta VIP0
    2022/6/16

     var value = Regex.Match(item.Name, @"\d{6}$").Value; 应该获取的是 6位数字

    0 回复
  • landon landon VIP0
    2022/6/17

    不是的,是我就用上面的代码运行,然后在执行正则的时候报错了,因为value是空,所以在value=value.Insert(4, "-");的时候就报错了,所以是否应该在这个前面加个判断,不为空才执行这部分代码

    value=value.Insert(4, "-");
                            tableInfo.Date = Convert.ToDateTime(value + "-01");
                            //tableInfo.String = null;  Time table, it doesn't work
                            //tableInfo.Long = null;  Time table, it doesn't work
                            result.Add(tableInfo);



    0 回复
  • landon landon VIP0
    2022/6/21

    已解决,需要加上value非空判断

    0 回复
  • 俗人 俗人 VIP0
    2023/12/13

    0 回复
  • ray ray VIP0
    2024/7/25

    @fate sta: ISplitTableService这个接口的方法,能不能写个详细的备注,分表的时候什么情况下会调用哪个方法? 现在分表我都搞不清什么情况下会调用哪个方法。

    0 回复
  • fan fan VIP0
    2025/2/7

    o我定义了一个,为什么执行这句, var registDataList = db.Queryable<MySpliteTest>().SplitTable(DateTime.Parse("2025/1/1"), DateTime.Now).ToList();查询时老提示找不到这个表,image.png

    0 回复
  • fate sta fate sta VIP0
    2025/2/14

    @fan:直接复制我给的现成的不要改东西

    0 回复
  • fate sta fate sta VIP0
    2025/2/14

    @fate sta:如果有改动就发新贴

    0 回复
  • using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Text.RegularExpressions;
    using SqlSugar;
    namespace OrmTest
    {
        public class Unitadfasdysss
        {
            public static void Init()
            {
                var db = NewUnitTest.Db;
                //建表 
                db.CodeFirst.InitTables<UnitTest22a001>();
                //清空表
                //插入测试数据
                var result = db.Insertable(new UnitTest22a001() { id = 1, ctime = DateTime.Parse("2025-03-25") })
                    .SplitTable().ExecuteCommand();//用例代码
                var startTime = DateTime.Parse("2025-03-03");
                var endTime = DateTime.Parse("2025-03-25");
                var dd = db.Queryable<UnitTest22a001>().Where(c => c.id == 1).SplitTable(startTime, endTime).ToList();
                /** 
                 * dd 返回结果是 no table 
                 * 查看源码后 发现 起始时间是日期不是1号,导致筛选不出分表
                 * 如果非常明确 SplitType._Custom01 针对按月分表的话,可以考虑 论坛中描述的
                  
                  
                 */ 
                Console.WriteLine(result);
                Console.WriteLine("用例跑完"); 
            }
            //建类
            [SplitTable(SplitType.Month, typeof(yyyyMMService))]
            [SugarTable("Unitxxx_{yyyyMM}")]
            public class UnitTest22a001
            {
                public int id { get; set; }
                [SplitField]
                public DateTime ctime { get; set; }
            }
        }
        public class yyyyMMService : ISplitTableService
        {
            public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
            {
                List<SplitTableInfo> result = new List<SplitTableInfo>();
                foreach (var item in tableInfos)
                {
                    var tableName = EntityInfo.DbTableName.Replace("_{yyyyMM}", "");
                    if (EntityInfo.DbTableName.Contains("_{yyyyMM}") && item.Name.Contains(tableName))// MySpliteTest_202204  这种格式的表
                    {
                        SplitTableInfo tableInfo = new SplitTableInfo();
                        tableInfo.TableName = item.Name;
                        var value = Regex.Match(item.Name, @"\d{6}$").Value;
                        if (value != null)
                        {
                            value = value.Insert(4, "-");
                            tableInfo.Date = Convert.ToDateTime(value + "-01");
                            //tableInfo.String = null;  Time table, it doesn't work
                            //tableInfo.Long = null;  Time table, it doesn't work
                            result.Add(tableInfo);
                        }
                    }
                }
                return result;
            }
            public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
            {
                var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
                if (splitColumn == null)
                {
                    return db.GetDate();
                }
                else
                {
                    var value = splitColumn.PropertyInfo.GetValue(entityValue, null);
                    return value;
                }
            }
            public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
            {
                return EntityInfo.DbTableName.Replace("{yyyyMM}", DateTime.Now.ToString("yyyyMM"));
            }
            public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type)
            {
                return EntityInfo.DbTableName.Replace("{yyyyMM}", DateTime.Now.ToString("yyyyMM"));
            }
            public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
            {
                return entityInfo.DbTableName.Replace("{yyyyMM}", Convert.ToDateTime(fieldValue).ToString("yyyyMM"));
            }
        }
    }


    0 回复
  • fate sta fate sta VIP0
    2025/4/30

    上面是完整示例

    0 回复