sqlsugar/Src/Asp.NetCore2/SqlSugar/IntegrationServices/SplitTableService.cs

280 lines
11 KiB
C#
Raw Permalink Normal View History

2025-05-11 16:20:50 +08:00
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace SqlSugar
{
public class DateSplitTableService : ISplitTableService
{
#region Core
public virtual List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
{
CheckTableName(EntityInfo.DbTableName);
var regex = "^"+EntityInfo.DbTableName.Replace("{year}", "([0-9]{2,4})").Replace("{day}", "([0-9]{1,2})").Replace("{month}", "([0-9]{1,2})");
var currentTables = tableInfos.Where(it => Regex.IsMatch(it.Name, regex, RegexOptions.IgnoreCase)).Select(it => it.Name).Reverse().ToList();
List<SplitTableInfo> result = new List<SplitTableInfo>();
foreach (var item in currentTables)
{
SplitTableInfo tableInfo = new SplitTableInfo();
tableInfo.TableName = item;
var math = Regex.Match(item, regex,RegexOptions.IgnoreCase);
var group1 = math.Groups[1].Value;
var group2 = math.Groups[2].Value;
var group3 = math.Groups[3].Value;
tableInfo.Date = GetDate(group1, group2, group3, EntityInfo.DbTableName);
//tableInfo.String = null; Time table, it doesn't work
//tableInfo.Long = null; Time table, it doesn't work
result.Add(tableInfo);
}
result = result.OrderByDescending(it => it.Date).ToList();
return result;
}
public virtual string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
{
var splitTableAttribute = EntityInfo.Type.GetCustomAttribute<SplitTableAttribute>();
if (splitTableAttribute != null)
{
var type=(splitTableAttribute as SplitTableAttribute).SplitType;
return GetTableName(db, EntityInfo, type);
}
else
{
return GetTableName(db, EntityInfo, SplitType.Day);
}
}
public virtual string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType splitType)
{
var date = db.GetDate();
return GetTableNameByDate(EntityInfo, splitType, date);
}
public virtual string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
{
var value = Convert.ToDateTime(fieldValue);
return GetTableNameByDate(entityInfo, splitType, value);
}
public virtual 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
{
if (entityValue == null)
{
return null;
}
var value = splitColumn.PropertyInfo.GetValue(entityValue, null);
if (value == null)
{
return db.GetDate();
}
else if (value is DateTimeOffset)
{
return ((DateTimeOffset)value).DateTime;
}
else if (UtilMethods.GetUnderType(value.GetType()) != UtilConstants.DateType)
{
throw new Exception($"DateSplitTableService Split column {splitColumn.PropertyName} not DateTime " + splitType.ToString());
}
else if (Convert.ToDateTime(value) == DateTime.MinValue)
{
return db.GetDate();
}
else
{
return value;
}
}
}
public void VerifySplitType(SplitType splitType)
{
switch (splitType)
{
case SplitType.Day:
break;
case SplitType.Week:
break;
case SplitType.Month:
break;
case SplitType.Season:
break;
case SplitType.Year:
break;
case SplitType.Month_6:
break;
default:
throw new Exception("DateSplitTableService no support " + splitType.ToString());
}
}
#endregion
#region Common Helper
private string GetTableNameByDate(EntityInfo EntityInfo,SplitType splitType,DateTime date)
{
date = ConvertDateBySplitType(date, splitType);
return EntityInfo.DbTableName.Replace("{year}", date.Year + "").Replace("{day}", PadLeft2(date.Day + "")).Replace("{month}", PadLeft2(date.Month + ""));
}
private DateTime GetDate(string group1, string group2, string group3, string dbTableName)
{
var yearIndex = dbTableName.IndexOf("{year}");
var dayIndex = dbTableName.IndexOf("{day}");
var monthIndex = dbTableName.IndexOf("{month}");
List<SplitTableSort> tables = new List<SplitTableSort>();
tables.Add(new SplitTableSort() { Name = "{year}", Sort = yearIndex });
tables.Add(new SplitTableSort() { Name = "{day}", Sort = dayIndex });
tables.Add(new SplitTableSort() { Name = "{month}", Sort = monthIndex });
tables = tables.OrderBy(it => it.Sort).ToList();
var year = "";
var month = "";
var day = "";
if (tables[0].Name == "{year}")
{
year = group1;
}
if (tables[1].Name == "{year}")
{
year = group2;
}
if (tables[2].Name == "{year}")
{
year = group3;
}
if (tables[0].Name == "{month}")
{
month = group1;
}
if (tables[1].Name == "{month}")
{
month = group2;
}
if (tables[2].Name == "{month}")
{
month = group3;
}
if (tables[0].Name == "{day}")
{
day = group1;
}
if (tables[1].Name == "{day}")
{
day = group2;
}
if (tables[2].Name == "{day}")
{
day = group3;
}
return Convert.ToDateTime($"{year}-{month}-{day}",CultureInfo.InvariantCulture);
}
private string PadLeft2(string str)
{
if (str.Length < 2)
{
return str.PadLeft(2, '0');
}
else
{
return str;
}
}
private static void CheckTableName(string dbTableName)
{
Check.Exception(!dbTableName.Contains("{year}"), ErrorMessage.GetThrowMessage("table name need {{year}}", "分表表名需要占位符 {{year}}"));
Check.Exception(!dbTableName.Contains("{month}"), ErrorMessage.GetThrowMessage("table name need {{month}}", "分表表名需要占位符 {{month}} "));
Check.Exception(!dbTableName.Contains("{day}"), ErrorMessage.GetThrowMessage("table name need {{day}}", "分表表名需要占位符{{day}}"));
Check.Exception(Regex.Matches(dbTableName, @"\{year\}").Count > 1, ErrorMessage.GetThrowMessage(" There can only be one {{year}}", " 只能有一个 {{year}}"));
Check.Exception(Regex.Matches(dbTableName, @"\{month\}").Count > 1, ErrorMessage.GetThrowMessage("There can only be one {{month}}", "只能有一个 {{month}} "));
Check.Exception(Regex.Matches(dbTableName, @"\{day\}").Count > 1, ErrorMessage.GetThrowMessage("There can only be one {{day}}", "只能有一个{{day}}"));
Check.Exception(Regex.IsMatch(dbTableName, @"\d\{|\}\d"), ErrorMessage.GetThrowMessage(" '{{' or '}}' can't be numbers nearby", "占位符相令一位不能是数字,比如 : 1{{day}}2 错误 , 正确: 1_{{day}}_2"));
}
#endregion
#region Date Helper
private DateTime ConvertDateBySplitType(DateTime time, SplitType type)
{
switch (type)
{
case SplitType.Day:
return Convert.ToDateTime(time.ToString("yyyy-MM-dd"));
case SplitType.Week:
return GetMondayDate(time);
case SplitType.Month:
return Convert.ToDateTime(time.ToString("yyyy-MM-01"));
case SplitType.Season:
if (time.Month <= 3)
{
return Convert.ToDateTime(time.ToString("yyyy-01-01"));
}
else if (time.Month <= 6)
{
return Convert.ToDateTime(time.ToString("yyyy-04-01"));
}
else if (time.Month <= 9)
{
return Convert.ToDateTime(time.ToString("yyyy-07-01"));
}
else
{
return Convert.ToDateTime(time.ToString("yyyy-10-01"));
}
case SplitType.Year:
return Convert.ToDateTime(time.ToString("yyyy-01-01"));
case SplitType.Month_6:
if (time.Month <= 6)
{
return Convert.ToDateTime(time.ToString("yyyy-01-01"));
}
else
{
return Convert.ToDateTime(time.ToString("yyyy-07-01"));
}
default:
throw new Exception($"SplitType parameter error ");
}
}
private DateTime GetMondayDate()
{
return GetMondayDate(DateTime.Now);
}
private DateTime GetSundayDate()
{
return GetSundayDate(DateTime.Now);
}
private DateTime GetMondayDate(DateTime someDate)
{
int i = someDate.DayOfWeek - DayOfWeek.Monday;
if (i == -1) i = 6;
TimeSpan ts = new TimeSpan(i, 0, 0, 0);
return someDate.Subtract(ts);
}
private DateTime GetSundayDate(DateTime someDate)
{
int i = someDate.DayOfWeek - DayOfWeek.Sunday;
if (i != 0) i = 7 - i;
TimeSpan ts = new TimeSpan(i, 0, 0, 0);
return someDate.Add(ts);
}
#endregion
#region Private Models
internal class SplitTableSort
{
public string Name { get; set; }
public int Sort { get; set; }
}
#endregion
}
}