版本更新后,更新分表数据时,分表名的时间后缀出现了( TableName_2026_07_2026_07 ) 返回

SqlSugar 待处理
5 248

分表名使用了自定义的写法(BasicSplitTableService : ISplitTableService)。

版本从5.1.4.126(旧版) 升级到了5.1.4.216(新版)。旧版BasicSplitTableService 时运行3年都正常。升级新版本后,创建、查询、删除都正常,但是更新分表数据时报错,出现了表名OperationRecord_2026_07_2026_07 的情况。更新的写法如下

DB.Updateable<OperationRecord>(records).UpdateColumns(UpdateColumns).Where(s => s.State != EnumExecuteState.Completed).WhereColumns(UpdateWhere).SplitTable(t => t.Take(3)).ExecuteCommandAsync();


请大佬抽空看看。BasicSplitTableService 代码如下

public class BasicSplitTableService : ISplitTableService{    private IFormatProvider TimeFormatProvider = new CultureInfo("zh-CN", true);    public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo entityInfo, List<DbTableInfo> tableInfos)
    {        List<SplitTableInfo> infos = new List<SplitTableInfo>();        foreach (var table in tableInfos.Where(s => s.Name.StartsWith(entityInfo.DbTableName)))
        {            string tbName = table.Name;            string splitInfo = tbName.Replace($"{entityInfo.DbTableName}_", string.Empty);            DateTime tbTime = DateTime.MinValue;            if (!DateTime.TryParseExact(splitInfo, "yyyy", TimeFormatProvider, DateTimeStyles.None, out tbTime)
                && !DateTime.TryParseExact(splitInfo, "yyyy_MM", TimeFormatProvider, DateTimeStyles.None, out tbTime)
                && !DateTime.TryParseExact(splitInfo, "yyyy_MM_dd", TimeFormatProvider, DateTimeStyles.None, out tbTime))
            {                if (splitInfo.Contains("_Season"))
                {                    string[] strs = splitInfo.Split("_Season");                    if (strs.Length > 1)
                    {                        int season = int.Parse(strs[1]);                        tbTime = new DateTime(int.Parse(strs[0]), 1, 1).AddMonths(season * 3);
                    }
                }                if (splitInfo.Contains("_Week"))
                {                    string[] strs = splitInfo.Split("_Week");                    if (strs.Length > 1)
                    {                        int week = int.Parse(strs[1]);                        tbTime = new DateTime(int.Parse(strs[0]), 1, 1).AddDays(week * 7);
                    }
                }                if (splitInfo.Contains("_Half"))
                {                    string[] strs = splitInfo.Split("_Half");                    if (strs.Length > 1)
                    {                        int half = int.Parse(strs[1]);                        tbTime = new DateTime(int.Parse(strs[0]), 1, 1).AddMonths(half * 6);
                    }
                }
            }            infos.Add(new SplitTableInfo
            {
                TableName = table.Name,
                Date = tbTime,
            });
        }        return infos.OrderByDescending(t => t.Date).ToList();
    }    public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
    {        EntityColumnInfo splitColumn = entityInfo.Columns.FirstOrDefault(s => s.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);        if (splitColumn == null)            return null;        return splitColumn.PropertyInfo.GetValue(entityValue);
    }    public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo)
    {        var attribute = entityInfo.Type.GetCustomAttribute<SplitTableAttribute>();        if (attribute == null)            return entityInfo.DbTableName;        return GetTableName(db, entityInfo, attribute.SplitType, DateTime.Now);
    }    public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType)
    {        return GetTableName(db, entityInfo, splitType, DateTime.Now);
    }    public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
    {        DateTime time;        if (fieldValue is DateTime t1)            time = t1;        else if (fieldValue is DateTimeOffset t2)            time = t2.UtcDateTime;        else
            throw new NotImplementedException("自定义分表字段仅支持DateTime/DateTimeOffset类型!");        switch (splitType)
        {            case SplitType.Year:                return $"{entityInfo.DbTableName}_{time:yyyy}";            case SplitType.Month:                return $"{entityInfo.DbTableName}_{time:yyyy_MM}";            case SplitType.Day:                return $"{entityInfo.DbTableName}_{time:yyyy_MM_dd}";            case SplitType.Week:
                {                    DateTime start = new DateTime(time.Year, 1, 1);                    var days = (int)((time.Date - start.Date).TotalDays);                    return $"{entityInfo.DbTableName}_{time.Year}_Week{(days / 7)}";
                }            case SplitType.Season:                return $"{entityInfo.DbTableName}_{time.Year}_Season{((time.Month - 1) / 3)}";            case SplitType.Month_6:                return $"{entityInfo.DbTableName}_{time.Year}_Half{((time.Month - 1) / 6)}";            default:                return $"{entityInfo.DbTableName}_{time:yyyy}";
        }

    }

}



热忱回答5

  • 重写的GetAllTables 看一下返回的值哪有问题

    0 回复
  • .Where(s => s.State != EnumExecuteState.Completed)

    批量更新,可能不支持这个where。只能用wherecolumns

    0 回复
  • @fate sta:  你好,我源码调试了一下 。在 

     SplitTableUpdateProvider<T> 这个类里,GetSqlObj(KeyValuePair<string, List<SugarParameter>> keyValuePair, string asName)这个方法里拼接sql出的问题。
    在  sql = Regex.Replace(sql, updateobj.EntityInfo.DbTableName, asName, RegexOptions.IgnoreCase); 这一行正则执行之前表名是对的 Data_OperationRecord_2026_07。执行后表名被替换成了 Data_OperationRecord_2026_07_2026_07

    企业微信截图_17842523177995.png

    企业微信截图_17842523559578.png

    0 回复
  • @fate sta:  你好,我发现是是2026年4月22日的提交,对SplitTableUpdateProvider<T>这个文件的修改导致的问题。 git提交Id是 380d5ada   .

    我把git版本回退到26年4月22号之前的版本,比如5.1.4.210版本,写法测试都是正常的。包括你说的

    .Where(s => s.State != EnumExecuteState.Completed)

    也都是支持的,生成的sql里有这个条件,执行正常。但是 修改文件之后的版本报错,也不支持 这个写法了

    0 回复
  • 5.1.4.216版本还有这个错么?是后续版本修复吗?

    0 回复