SplitTableService.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reflection;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using System.Threading.Tasks;
  8. namespace SqlSugar
  9. {
  10. public class DateSplitTableService : ISplitTableService
  11. {
  12. #region Core
  13. public virtual List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
  14. {
  15. CheckTableName(EntityInfo.DbTableName);
  16. var regex = "^"+EntityInfo.DbTableName.Replace("{year}", "([0-9]{2,4})").Replace("{day}", "([0-9]{1,2})").Replace("{month}", "([0-9]{1,2})");
  17. var currentTables = tableInfos.Where(it => Regex.IsMatch(it.Name, regex, RegexOptions.IgnoreCase)).Select(it => it.Name).Reverse().ToList();
  18. List<SplitTableInfo> result = new List<SplitTableInfo>();
  19. foreach (var item in currentTables)
  20. {
  21. SplitTableInfo tableInfo = new SplitTableInfo();
  22. tableInfo.TableName = item;
  23. var math = Regex.Match(item, regex,RegexOptions.IgnoreCase);
  24. var group1 = math.Groups[1].Value;
  25. var group2 = math.Groups[2].Value;
  26. var group3 = math.Groups[3].Value;
  27. tableInfo.Date = GetDate(group1, group2, group3, EntityInfo.DbTableName);
  28. //tableInfo.String = null; Time table, it doesn't work
  29. //tableInfo.Long = null; Time table, it doesn't work
  30. result.Add(tableInfo);
  31. }
  32. result = result.OrderByDescending(it => it.Date).ToList();
  33. return result;
  34. }
  35. public virtual string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
  36. {
  37. var splitTableAttribute = EntityInfo.Type.GetCustomAttribute<SplitTableAttribute>();
  38. if (splitTableAttribute != null)
  39. {
  40. var type=(splitTableAttribute as SplitTableAttribute).SplitType;
  41. return GetTableName(db, EntityInfo, type);
  42. }
  43. else
  44. {
  45. return GetTableName(db, EntityInfo, SplitType.Day);
  46. }
  47. }
  48. public virtual string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType splitType)
  49. {
  50. var date = db.GetDate();
  51. return GetTableNameByDate(EntityInfo, splitType, date);
  52. }
  53. public virtual string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
  54. {
  55. var value = Convert.ToDateTime(fieldValue);
  56. return GetTableNameByDate(entityInfo, splitType, value);
  57. }
  58. public virtual object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
  59. {
  60. var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
  61. if (splitColumn == null)
  62. {
  63. return db.GetDate();
  64. }
  65. else
  66. {
  67. if (entityValue == null)
  68. {
  69. return null;
  70. }
  71. var value = splitColumn.PropertyInfo.GetValue(entityValue, null);
  72. if (value == null)
  73. {
  74. return db.GetDate();
  75. }
  76. else if (value is DateTimeOffset)
  77. {
  78. return ((DateTimeOffset)value).DateTime;
  79. }
  80. else if (UtilMethods.GetUnderType(value.GetType()) != UtilConstants.DateType)
  81. {
  82. throw new Exception($"DateSplitTableService Split column {splitColumn.PropertyName} not DateTime " + splitType.ToString());
  83. }
  84. else if (Convert.ToDateTime(value) == DateTime.MinValue)
  85. {
  86. return db.GetDate();
  87. }
  88. else
  89. {
  90. return value;
  91. }
  92. }
  93. }
  94. public void VerifySplitType(SplitType splitType)
  95. {
  96. switch (splitType)
  97. {
  98. case SplitType.Day:
  99. break;
  100. case SplitType.Week:
  101. break;
  102. case SplitType.Month:
  103. break;
  104. case SplitType.Season:
  105. break;
  106. case SplitType.Year:
  107. break;
  108. case SplitType.Month_6:
  109. break;
  110. default:
  111. throw new Exception("DateSplitTableService no support " + splitType.ToString());
  112. }
  113. }
  114. #endregion
  115. #region Common Helper
  116. private string GetTableNameByDate(EntityInfo EntityInfo,SplitType splitType,DateTime date)
  117. {
  118. date = ConvertDateBySplitType(date, splitType);
  119. return EntityInfo.DbTableName.Replace("{year}", date.Year + "").Replace("{day}", PadLeft2(date.Day + "")).Replace("{month}", PadLeft2(date.Month + ""));
  120. }
  121. private DateTime GetDate(string group1, string group2, string group3, string dbTableName)
  122. {
  123. var yearIndex = dbTableName.IndexOf("{year}");
  124. var dayIndex = dbTableName.IndexOf("{day}");
  125. var monthIndex = dbTableName.IndexOf("{month}");
  126. List<SplitTableSort> tables = new List<SplitTableSort>();
  127. tables.Add(new SplitTableSort() { Name = "{year}", Sort = yearIndex });
  128. tables.Add(new SplitTableSort() { Name = "{day}", Sort = dayIndex });
  129. tables.Add(new SplitTableSort() { Name = "{month}", Sort = monthIndex });
  130. tables = tables.OrderBy(it => it.Sort).ToList();
  131. var year = "";
  132. var month = "";
  133. var day = "";
  134. if (tables[0].Name == "{year}")
  135. {
  136. year = group1;
  137. }
  138. if (tables[1].Name == "{year}")
  139. {
  140. year = group2;
  141. }
  142. if (tables[2].Name == "{year}")
  143. {
  144. year = group3;
  145. }
  146. if (tables[0].Name == "{month}")
  147. {
  148. month = group1;
  149. }
  150. if (tables[1].Name == "{month}")
  151. {
  152. month = group2;
  153. }
  154. if (tables[2].Name == "{month}")
  155. {
  156. month = group3;
  157. }
  158. if (tables[0].Name == "{day}")
  159. {
  160. day = group1;
  161. }
  162. if (tables[1].Name == "{day}")
  163. {
  164. day = group2;
  165. }
  166. if (tables[2].Name == "{day}")
  167. {
  168. day = group3;
  169. }
  170. return Convert.ToDateTime($"{year}-{month}-{day}");
  171. }
  172. private string PadLeft2(string str)
  173. {
  174. if (str.Length < 2)
  175. {
  176. return str.PadLeft(2, '0');
  177. }
  178. else
  179. {
  180. return str;
  181. }
  182. }
  183. private static void CheckTableName(string dbTableName)
  184. {
  185. Check.Exception(!dbTableName.Contains("{year}"), ErrorMessage.GetThrowMessage("table name need {{year}}", "分表表名需要占位符 {{year}}"));
  186. Check.Exception(!dbTableName.Contains("{month}"), ErrorMessage.GetThrowMessage("table name need {{month}}", "分表表名需要占位符 {{month}} "));
  187. Check.Exception(!dbTableName.Contains("{day}"), ErrorMessage.GetThrowMessage("table name need {{day}}", "分表表名需要占位符{{day}}"));
  188. Check.Exception(Regex.Matches(dbTableName, @"\{year\}").Count > 1, ErrorMessage.GetThrowMessage(" There can only be one {{year}}", " 只能有一个 {{year}}"));
  189. Check.Exception(Regex.Matches(dbTableName, @"\{month\}").Count > 1, ErrorMessage.GetThrowMessage("There can only be one {{month}}", "只能有一个 {{month}} "));
  190. Check.Exception(Regex.Matches(dbTableName, @"\{day\}").Count > 1, ErrorMessage.GetThrowMessage("There can only be one {{day}}", "只能有一个{{day}}"));
  191. Check.Exception(Regex.IsMatch(dbTableName, @"\d\{|\}\d"), ErrorMessage.GetThrowMessage(" '{{' or '}}' can't be numbers nearby", "占位符相令一位不能是数字,比如 : 1{{day}}2 错误 , 正确: 1_{{day}}_2"));
  192. }
  193. #endregion
  194. #region Date Helper
  195. private DateTime ConvertDateBySplitType(DateTime time, SplitType type)
  196. {
  197. switch (type)
  198. {
  199. case SplitType.Day:
  200. return Convert.ToDateTime(time.ToString("yyyy-MM-dd"));
  201. case SplitType.Week:
  202. return GetMondayDate(time);
  203. case SplitType.Month:
  204. return Convert.ToDateTime(time.ToString("yyyy-MM-01"));
  205. case SplitType.Season:
  206. if (time.Month <= 3)
  207. {
  208. return Convert.ToDateTime(time.ToString("yyyy-01-01"));
  209. }
  210. else if (time.Month <= 6)
  211. {
  212. return Convert.ToDateTime(time.ToString("yyyy-04-01"));
  213. }
  214. else if (time.Month <= 9)
  215. {
  216. return Convert.ToDateTime(time.ToString("yyyy-07-01"));
  217. }
  218. else
  219. {
  220. return Convert.ToDateTime(time.ToString("yyyy-10-01"));
  221. }
  222. case SplitType.Year:
  223. return Convert.ToDateTime(time.ToString("yyyy-01-01"));
  224. case SplitType.Month_6:
  225. if (time.Month <= 6)
  226. {
  227. return Convert.ToDateTime(time.ToString("yyyy-01-01"));
  228. }
  229. else
  230. {
  231. return Convert.ToDateTime(time.ToString("yyyy-07-01"));
  232. }
  233. default:
  234. throw new Exception($"SplitType parameter error ");
  235. }
  236. }
  237. private DateTime GetMondayDate()
  238. {
  239. return GetMondayDate(DateTime.Now);
  240. }
  241. private DateTime GetSundayDate()
  242. {
  243. return GetSundayDate(DateTime.Now);
  244. }
  245. private DateTime GetMondayDate(DateTime someDate)
  246. {
  247. int i = someDate.DayOfWeek - DayOfWeek.Monday;
  248. if (i == -1) i = 6;
  249. TimeSpan ts = new TimeSpan(i, 0, 0, 0);
  250. return someDate.Subtract(ts);
  251. }
  252. private DateTime GetSundayDate(DateTime someDate)
  253. {
  254. int i = someDate.DayOfWeek - DayOfWeek.Sunday;
  255. if (i != 0) i = 7 - i;
  256. TimeSpan ts = new TimeSpan(i, 0, 0, 0);
  257. return someDate.Add(ts);
  258. }
  259. #endregion
  260. #region Private Models
  261. internal class SplitTableSort
  262. {
  263. public string Name { get; set; }
  264. public int Sort { get; set; }
  265. }
  266. #endregion
  267. }
  268. }