You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

426 lines
19 KiB

2 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. namespace SqlSugar
  8. {
  9. public abstract partial class DbFirstProvider : IDbFirst
  10. {
  11. public virtual SqlSugarClient Context { get; set; }
  12. private string ClassTemplate { get; set; }
  13. private string ClassDescriptionTemplate { get; set; }
  14. private string PropertyTemplate { get; set; }
  15. private string PropertyCostTemplate { get; set; }
  16. private string PropertyDescriptionTemplate { get; set; }
  17. private string ConstructorTemplate { get; set; }
  18. private string UsingTemplate { get; set; }
  19. private string Namespace { get; set; }
  20. private bool IsAttribute { get; set; }
  21. private bool IsDefaultValue { get; set; }
  22. private ISqlBuilder SqlBuilder
  23. {
  24. get
  25. {
  26. return InstanceFactory.GetSqlbuilder(this.Context.CurrentConnectionConfig);
  27. }
  28. }
  29. private List<DbTableInfo> TableInfoList { get; set; }
  30. protected DbFirstProvider()
  31. {
  32. this.ClassTemplate = DbFirstTemplate.ClassTemplate;
  33. this.ClassDescriptionTemplate = DbFirstTemplate.ClassDescriptionTemplate;
  34. this.PropertyTemplate = DbFirstTemplate.PropertyTemplate;
  35. this.PropertyCostTemplate = DbFirstTemplate.PropertyConstNameTemplate;
  36. this.PropertyDescriptionTemplate = DbFirstTemplate.PropertyDescriptionTemplate;
  37. this.ConstructorTemplate = DbFirstTemplate.ConstructorTemplate;
  38. this.UsingTemplate = DbFirstTemplate.UsingTemplate;
  39. }
  40. public void Init()
  41. {
  42. this.Context.Utilities.RemoveCacheAll();
  43. if (!this.Context.DbMaintenance.IsAnySystemTablePermissions())
  44. {
  45. Check.Exception(true, "Dbfirst and Codefirst requires system table permissions");
  46. }
  47. this.TableInfoList = this.Context.Utilities.TranslateCopy(this.Context.DbMaintenance.GetTableInfoList());
  48. var viewList = this.Context.Utilities.TranslateCopy(this.Context.DbMaintenance.GetViewInfoList());
  49. if (viewList.HasValue())
  50. {
  51. this.TableInfoList.AddRange(viewList);
  52. }
  53. }
  54. #region Setting Template
  55. public IDbFirst SettingClassDescriptionTemplate(Func<string, string> func)
  56. {
  57. this.ClassDescriptionTemplate = func?.Invoke(this.ClassDescriptionTemplate);
  58. return this;
  59. }
  60. public IDbFirst SettingClassTemplate(Func<string, string> func)
  61. {
  62. this.ClassTemplate = func?.Invoke(this.ClassTemplate);
  63. return this;
  64. }
  65. public IDbFirst SettingConstructorTemplate(Func<string, string> func)
  66. {
  67. this.ConstructorTemplate = func?.Invoke(this.ConstructorTemplate);
  68. return this;
  69. }
  70. public IDbFirst SettingPropertyDescriptionTemplate(Func<string, string> func)
  71. {
  72. this.PropertyDescriptionTemplate = func?.Invoke(this.PropertyDescriptionTemplate);
  73. return this;
  74. }
  75. public IDbFirst SettingNamespaceTemplate(Func<string, string> func)
  76. {
  77. this.UsingTemplate = func?.Invoke(this.UsingTemplate);
  78. return this;
  79. }
  80. public IDbFirst SettingPropertyTemplate(Func<string, string> func)
  81. {
  82. this.PropertyTemplate = func?.Invoke(this.PropertyTemplate);
  83. return this;
  84. }
  85. #endregion Setting Template
  86. #region Setting Content
  87. public IDbFirst IsCreateAttribute(bool isCreateAttribute = true)
  88. {
  89. this.IsAttribute = isCreateAttribute;
  90. return this;
  91. }
  92. public IDbFirst IsCreateDefaultValue(bool isCreateDefaultValue = true)
  93. {
  94. this.IsDefaultValue = isCreateDefaultValue;
  95. return this;
  96. }
  97. #endregion Setting Content
  98. #region Where
  99. public IDbFirst Where(DbObjectType dbObjectType)
  100. {
  101. if (dbObjectType != DbObjectType.All)
  102. this.TableInfoList = this.TableInfoList.Where(it => it.DbObjectType == dbObjectType).ToList();
  103. return this;
  104. }
  105. public IDbFirst Where(Func<string, bool> func)
  106. {
  107. this.TableInfoList = this.TableInfoList.Where(it => func?.Invoke(it.Name) ?? default(bool)).ToList();
  108. return this;
  109. }
  110. public IDbFirst Where(params string[] objectNames)
  111. {
  112. if (objectNames.HasValue())
  113. {
  114. this.TableInfoList = this.TableInfoList.Where(it => objectNames.Contains(it.Name)).ToList();
  115. }
  116. return this;
  117. }
  118. #endregion Where
  119. #region Core
  120. public Dictionary<string, string> ToClassStringList(string nameSpace = "Models")
  121. {
  122. this.Namespace = nameSpace;
  123. var result = new Dictionary<string, string>();
  124. if (this.TableInfoList.HasValue())
  125. {
  126. foreach (var tableInfo in this.TableInfoList)
  127. {
  128. try
  129. {
  130. string classText = null;
  131. var className = tableInfo.Name;
  132. classText = GetClassString(tableInfo, ref className);
  133. result.Remove(className);
  134. result.Add(className, classText);
  135. }
  136. catch (Exception ex)
  137. {
  138. Check.Exception(true, "Table '{0}' error,You can filter it with Db.DbFirst.Where(name=>name!=\"{0}\" ) \r\n Error message:{1}", tableInfo.Name, ex.Message);
  139. }
  140. }
  141. }
  142. return result;
  143. }
  144. internal string GetClassString(DbTableInfo tableInfo, ref string className)
  145. {
  146. string classText;
  147. var columns = this.Context.DbMaintenance.GetColumnInfosByTableName(tableInfo.Name);
  148. if (this.Context.IgnoreColumns.HasValue())
  149. {
  150. var entityName = this.Context.EntityMaintenance.GetEntityName(tableInfo.Name);
  151. columns = columns.Where(c =>
  152. !this.Context.IgnoreColumns.Any(ig => ig.EntityName.Equals(entityName, StringComparison.CurrentCultureIgnoreCase) && c.DbColumnName == ig.PropertyName)
  153. ).ToList();
  154. }
  155. classText = this.ClassTemplate;
  156. var ConstructorText = IsDefaultValue ? this.ConstructorTemplate : null;
  157. if (this.Context.MappingTables.HasValue())
  158. {
  159. var mappingInfo = this.Context.MappingTables.FirstOrDefault(it => it.DbTableName.Equals(tableInfo.Name, StringComparison.CurrentCultureIgnoreCase));
  160. if (mappingInfo.HasValue())
  161. {
  162. className = mappingInfo.EntityName;
  163. }
  164. if (mappingInfo != null)
  165. {
  166. classText = classText.Replace(DbFirstTemplate.KeyClassName, mappingInfo.EntityName);
  167. }
  168. }
  169. classText = classText.Replace(DbFirstTemplate.KeyClassName, className);
  170. classText = classText.Replace(DbFirstTemplate.KeyNamespace, this.Namespace);
  171. classText = classText.Replace(DbFirstTemplate.KeyUsing, IsAttribute ? (this.UsingTemplate + "using " + UtilConstants.AssemblyName + ";\r\n") : this.UsingTemplate);
  172. classText = classText.Replace(DbFirstTemplate.KeyClassDescription, this.ClassDescriptionTemplate.Replace(DbFirstTemplate.KeyClassDescription, tableInfo.Description + "\r\n"));
  173. classText = classText.Replace(DbFirstTemplate.KeySugarTable, IsAttribute ? string.Format(DbFirstTemplate.ValueSugarTable, tableInfo.Name) : null);
  174. if (columns.HasValue())
  175. {
  176. foreach (var item in columns)
  177. {
  178. var isLast = columns.Last() == item;
  179. var index = columns.IndexOf(item);
  180. var PropertyText = this.PropertyTemplate;
  181. var PropertyCostText = this.PropertyCostTemplate;
  182. var PropertyDescriptionText = this.PropertyDescriptionTemplate;
  183. var propertyName = GetPropertyName(item);
  184. var propertyTypeName = GetPropertyTypeName(item);
  185. PropertyText = GetPropertyText(item, PropertyText);
  186. PropertyCostText = GetPropertyCostText(item, PropertyCostText);
  187. PropertyDescriptionText = GetPropertyDescriptionText(item, PropertyDescriptionText);
  188. PropertyText = PropertyDescriptionText + PropertyText + PropertyCostText;
  189. classText = classText.Replace(DbFirstTemplate.KeyPropertyName, PropertyText + (isLast ? "" : ("\r\n" + DbFirstTemplate.KeyPropertyName)));
  190. if (ConstructorText.HasValue() && item.DefaultValue != null)
  191. {
  192. var hasDefaultValue = columns.Skip(index + 1).Any(it => it.DefaultValue.HasValue());
  193. ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyPropertyName, propertyName);
  194. ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyDefaultValue, GetPropertyTypeConvert(item)) + (!hasDefaultValue ? "" : this.ConstructorTemplate);
  195. }
  196. }
  197. }
  198. if (!columns.Any(it => it.DefaultValue != null))
  199. {
  200. ConstructorText = null;
  201. }
  202. classText = classText.Replace(DbFirstTemplate.KeyConstructor, ConstructorText);
  203. classText = classText.Replace(DbFirstTemplate.KeyPropertyName, null);
  204. return classText;
  205. }
  206. internal string GetClassString(List<DbColumnInfo> columns, ref string className)
  207. {
  208. var classText = this.ClassTemplate;
  209. var ConstructorText = IsDefaultValue ? this.ConstructorTemplate : null;
  210. classText = classText.Replace(DbFirstTemplate.KeyClassName, className);
  211. classText = classText.Replace(DbFirstTemplate.KeyNamespace, this.Namespace);
  212. classText = classText.Replace(DbFirstTemplate.KeyUsing, IsAttribute ? (this.UsingTemplate + "using " + UtilConstants.AssemblyName + ";\r\n") : this.UsingTemplate);
  213. classText = classText.Replace(DbFirstTemplate.KeyClassDescription, this.ClassDescriptionTemplate.Replace(DbFirstTemplate.KeyClassDescription, "\r\n"));
  214. classText = classText.Replace(DbFirstTemplate.KeySugarTable, IsAttribute ? string.Format(DbFirstTemplate.ValueSugarTable, className) : null);
  215. if (columns.HasValue())
  216. {
  217. foreach (var item in columns)
  218. {
  219. var isLast = columns.Last() == item;
  220. var index = columns.IndexOf(item);
  221. var PropertyText = this.PropertyTemplate;
  222. var PropertyCostText = this.PropertyCostTemplate;
  223. var PropertyDescriptionText = this.PropertyDescriptionTemplate;
  224. var propertyName = GetPropertyName(item);
  225. var propertyTypeName = item.PropertyName;
  226. PropertyText = GetPropertyText(item, PropertyText);
  227. PropertyCostText = GetPropertyCostText(item, PropertyText);
  228. PropertyDescriptionText = GetPropertyDescriptionText(item, PropertyDescriptionText);
  229. PropertyText = PropertyDescriptionText + PropertyText + PropertyCostText;
  230. classText = classText.Replace(DbFirstTemplate.KeyPropertyName, PropertyText + (isLast ? "" : ("\r\n" + DbFirstTemplate.KeyPropertyName)));
  231. if (ConstructorText.HasValue() && item.DefaultValue != null)
  232. {
  233. var hasDefaultValue = columns.Skip(index + 1).Any(it => it.DefaultValue.HasValue());
  234. ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyPropertyName, propertyName);
  235. ConstructorText = ConstructorText.Replace(DbFirstTemplate.KeyDefaultValue, GetPropertyTypeConvert(item)) + (!hasDefaultValue ? "" : this.ConstructorTemplate);
  236. }
  237. }
  238. }
  239. if (!columns.Any(it => it.DefaultValue != null))
  240. {
  241. ConstructorText = null;
  242. }
  243. classText = classText.Replace(DbFirstTemplate.KeyConstructor, ConstructorText);
  244. classText = classText.Replace(DbFirstTemplate.KeyPropertyName, null);
  245. return classText;
  246. }
  247. public void CreateClassFile(string directoryPath, string nameSpace = "Models")
  248. {
  249. var seChar = Path.DirectorySeparatorChar.ToString();
  250. Check.ArgumentNullException(directoryPath, "directoryPath can't null");
  251. var classStringList = ToClassStringList(nameSpace);
  252. if (classStringList.IsValuable())
  253. {
  254. foreach (var item in classStringList)
  255. {
  256. var filePath = directoryPath.TrimEnd('\\').TrimEnd('/') + string.Format(seChar + "{0}.cs", item.Key);
  257. FileHelper.CreateFile(filePath, item.Value, Encoding.UTF8);
  258. }
  259. }
  260. }
  261. #endregion Core
  262. #region Private methods
  263. private string GetProertypeDefaultValue(DbColumnInfo item)
  264. {
  265. var result = item.DefaultValue;
  266. if (result == null) return null;
  267. if (Regex.IsMatch(result, @"^\(\'(.+)\'\)$"))
  268. {
  269. result = Regex.Match(result, @"^\(\'(.+)\'\)$").Groups[1].Value;
  270. }
  271. if (Regex.IsMatch(result, @"^\(\((.+)\)\)$"))
  272. {
  273. result = Regex.Match(result, @"^\(\((.+)\)\)$").Groups[1].Value;
  274. }
  275. if (Regex.IsMatch(result, @"^\((.+)\)$"))
  276. {
  277. result = Regex.Match(result, @"^\((.+)\)$").Groups[1].Value;
  278. }
  279. if (result.Equals(this.SqlBuilder.SqlDateNow, StringComparison.CurrentCultureIgnoreCase))
  280. {
  281. result = "DateTime.Now";
  282. }
  283. result = result.Replace("\r", "\t").Replace("\n", "\t");
  284. result = result.IsIn("''", "\"\"") ? string.Empty : result;
  285. return result;
  286. }
  287. private string GetPropertyText(DbColumnInfo item, string PropertyText)
  288. {
  289. var SugarColumnText = DbFirstTemplate.ValueSugarCoulmn;
  290. var propertyName = GetPropertyName(item);
  291. var isMappingColumn = propertyName != item.DbColumnName;
  292. var hasSugarColumn = item.IsPrimarykey || item.IsIdentity || isMappingColumn;
  293. if (hasSugarColumn && this.IsAttribute)
  294. {
  295. var joinList = new List<string>();
  296. if (item.IsPrimarykey)
  297. {
  298. joinList.Add("IsPrimaryKey=true");
  299. }
  300. if (item.IsIdentity)
  301. {
  302. joinList.Add("IsIdentity=true");
  303. }
  304. if (isMappingColumn)
  305. {
  306. joinList.Add("ColumnName=\"" + item.DbColumnName + "\"");
  307. }
  308. SugarColumnText = string.Format(SugarColumnText, string.Join(",", joinList));
  309. }
  310. else
  311. {
  312. SugarColumnText = null;
  313. }
  314. var typeString = GetPropertyTypeName(item);
  315. PropertyText = PropertyText.Replace(DbFirstTemplate.KeySugarColumn, SugarColumnText);
  316. PropertyText = PropertyText.Replace(DbFirstTemplate.KeyPropertyType, typeString);
  317. PropertyText = PropertyText.Replace(DbFirstTemplate.KeyPropertyName, propertyName);
  318. return PropertyText;
  319. }
  320. private string GetPropertyCostText(DbColumnInfo item, string PropertyText)
  321. {
  322. var propertyName = GetPropertyName(item);
  323. PropertyText = PropertyText.Replace(DbFirstTemplate.KeyPropertyConstName, propertyName.ToUpper());
  324. PropertyText = PropertyText.Replace(DbFirstTemplate.KeyPropertyName, propertyName);
  325. return PropertyText;
  326. }
  327. private string GetEnityName(DbColumnInfo item)
  328. {
  329. var mappingInfo = this.Context.MappingTables.FirstOrDefault(it => it.DbTableName.Equals(item.TableName, StringComparison.CurrentCultureIgnoreCase));
  330. return mappingInfo == null ? item.TableName : mappingInfo.EntityName;
  331. }
  332. private string GetPropertyName(DbColumnInfo item)
  333. {
  334. if (this.Context.MappingColumns.HasValue())
  335. {
  336. var mappingInfo = this.Context.MappingColumns.SingleOrDefault(it => it.DbColumnName == item.DbColumnName && it.EntityName == GetEnityName(item));
  337. return mappingInfo == null ? item.DbColumnName : mappingInfo.PropertyName;
  338. }
  339. else
  340. {
  341. return item.DbColumnName;
  342. }
  343. }
  344. private string GetPropertyTypeName(DbColumnInfo item)
  345. {
  346. var result = item.PropertyType != null ? item.PropertyType.Name : this.Context.Ado.DbBind.GetPropertyTypeName(item.DataType);
  347. if (result != "string" && result != "byte[]" && result != "object" && item.IsNullable)
  348. {
  349. result += "?";
  350. }
  351. if (result == "Int32")
  352. {
  353. result = "int";
  354. }
  355. if (result == "String")
  356. {
  357. result = "string";
  358. }
  359. return result;
  360. }
  361. private string GetPropertyTypeConvert(DbColumnInfo item)
  362. {
  363. var convertString = GetProertypeDefaultValue(item);
  364. if (convertString == "DateTime.Now" || convertString == null)
  365. return convertString;
  366. if (item.DataType == "bit")
  367. return (convertString == "1" || convertString.Equals("true", StringComparison.CurrentCultureIgnoreCase)).ToString().ToLower();
  368. var result = this.Context.Ado.DbBind.GetConvertString(item.DataType) + "(\"" + convertString + "\")";
  369. return result;
  370. }
  371. private string GetPropertyDescriptionText(DbColumnInfo item, string propertyDescriptionText)
  372. {
  373. propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyPropertyDescription, GetColumnDescription(item.ColumnDescription));
  374. propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyDefaultValue, GetProertypeDefaultValue(item));
  375. propertyDescriptionText = propertyDescriptionText.Replace(DbFirstTemplate.KeyIsNullable, item.IsNullable.ObjToString());
  376. return propertyDescriptionText;
  377. }
  378. private string GetColumnDescription(string columnDescription)
  379. {
  380. if (columnDescription == null) return columnDescription;
  381. columnDescription = columnDescription.Replace("\r", "\t");
  382. columnDescription = columnDescription.Replace("\n", "\t");
  383. columnDescription = Regex.Replace(columnDescription, "\t{2,}", "\t");
  384. return columnDescription;
  385. }
  386. #endregion Private methods
  387. }
  388. }