MySqlSync.cs 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel.DataAnnotations.Schema;
  4. using System.Data.Entity;
  5. using System.Linq;
  6. using System.Linq.Expressions;
  7. using System.Reflection;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using XdCxRhDW.Entity;
  11. namespace XdCxRhDW.Repostory
  12. {
  13. class DbTableColumnInfo
  14. {
  15. public string name { get; set; }
  16. public string type { get; set; }
  17. public int notnull { get; set; }
  18. public int pk { get; set; }
  19. }
  20. public class MySqlSync : MySqlContext
  21. {
  22. private string database;
  23. public MySqlSync()
  24. {
  25. database = this.Database.Connection.Database;
  26. }
  27. /// <summary>
  28. /// 同步数据库表、字段、索引
  29. /// </summary>
  30. public void SyncDb()
  31. {
  32. SyncTable();
  33. SyncTableField();
  34. SyncIndex();
  35. }
  36. void SyncTable()
  37. {
  38. var tables = this.Database.SqlQuery<string>($"select table_name from information_schema.tables where table_schema='{database}'").ToList();
  39. var props = this.GetType().GetProperties();
  40. Dictionary<string, Type> list = new Dictionary<string, Type>();
  41. foreach (var prop in props)
  42. {
  43. bool isDbSet = prop.PropertyType.IsGenericType && typeof(DbSet<>) == prop.PropertyType.GetGenericTypeDefinition();
  44. if (isDbSet)
  45. {
  46. var entityType = prop.PropertyType.GenericTypeArguments[0];
  47. var name = entityType.GetCustomAttribute<TableAttribute>()?.Name;
  48. if (name == null)
  49. {
  50. name = entityType.Name;
  51. }
  52. list.Add(name, entityType);
  53. }
  54. }
  55. foreach (var item in list)
  56. {
  57. if (!tables.Any(p => p.ToLower() == item.Key.ToLower()))
  58. {
  59. var entityProps = item.Value.GetProperties().Where(p =>
  60. p.CanRead
  61. && p.CanWrite
  62. && !p.GetMethod.IsVirtual
  63. && p.GetCustomAttribute<NotMappedAttribute>() == null);
  64. item.Value.GetProperties().Where(p => p.CanWrite);
  65. StringBuilder sb = new StringBuilder();
  66. sb.Append($"create table {item.Key}(ID integer primary key autoincrement");
  67. foreach (var prop in entityProps)
  68. {
  69. if (prop.Name.ToLower() == "id") continue;
  70. bool isNullable = prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
  71. string typeStr = "";
  72. var type = prop.PropertyType;
  73. if (prop.PropertyType.IsGenericType)
  74. {
  75. type = prop.PropertyType.GenericTypeArguments[0];
  76. }
  77. if (type == typeof(string))
  78. {
  79. typeStr = "nvarchar";
  80. }
  81. else if (type == typeof(int) || type == typeof(long) || prop.PropertyType.IsEnum)
  82. {
  83. typeStr = "int";
  84. }
  85. else if (type == typeof(double) || type == typeof(float))
  86. {
  87. typeStr = "float";
  88. }
  89. else if (type == typeof(DateTime))
  90. {
  91. typeStr = "datetime";
  92. }
  93. sb.Append($",{prop.Name} {typeStr}");
  94. if (!isNullable)
  95. {
  96. sb.Append(" not null");
  97. }
  98. }
  99. sb.Append(")");
  100. string createTableSql = sb.ToString();
  101. Database.ExecuteSqlCommand(createTableSql);
  102. }
  103. }
  104. }
  105. void SyncIndex()
  106. {
  107. var tables = this.Database.SqlQuery<string>("select name from sqlite_master where type='table' and name not like 'sqlite%'").ToList();
  108. var props = this.GetType().GetProperties();
  109. List<Type> entityTypes = new List<Type>();
  110. foreach (var prop in props)
  111. {
  112. bool isDbSet = prop.PropertyType.IsGenericType && typeof(DbSet<>) == prop.PropertyType.GetGenericTypeDefinition();
  113. if (isDbSet)
  114. {
  115. var entityType = prop.PropertyType.GenericTypeArguments[0];
  116. entityTypes.Add(entityType);
  117. }
  118. }
  119. foreach (var table in tables)
  120. {
  121. var res = this.Database.SqlQuery<DbTableColumnInfo>($"PRAGMA table_info([{table}])").ToList();
  122. var entityType = entityTypes.FirstOrDefault(p => p.Name == table);
  123. if (entityType == null) continue;
  124. //创建具有Index特性的索引列
  125. var entityProps = entityType.GetProperties().Where(p =>
  126. p.CanRead
  127. && p.Name.ToUpper() != "ID"
  128. && p.CanWrite
  129. && !p.GetMethod.IsVirtual
  130. && p.GetCustomAttribute<IndexAttribute>() != null
  131. && p.GetCustomAttribute<NotMappedAttribute>() == null);
  132. foreach (var prop in entityProps)
  133. {
  134. var index = this.Database.SqlQuery<string>($"SELECT name FROM sqlite_master WHERE type='index' AND tbl_name='{table}' and name='IX_{table}_{prop.Name}'").FirstOrDefault();
  135. if (index == null)
  136. {
  137. this.Database.ExecuteSqlCommand($"CREATE INDEX 'IX_{table}_{prop.Name}' ON {table} ('{prop.Name}')");
  138. }
  139. }
  140. }
  141. }
  142. void SyncTableField()
  143. {
  144. var tables = this.Database.SqlQuery<string>("select name from sqlite_master where type='table' and name not like 'sqlite%'").ToList();
  145. var props = this.GetType().GetProperties();
  146. List<Type> entityTypes = new List<Type>();
  147. foreach (var prop in props)
  148. {
  149. bool isDbSet = prop.PropertyType.IsGenericType && typeof(DbSet<>) == prop.PropertyType.GetGenericTypeDefinition();
  150. if (isDbSet)
  151. {
  152. var entityType = prop.PropertyType.GenericTypeArguments[0];
  153. entityTypes.Add(entityType);
  154. }
  155. }
  156. foreach (var table in tables)
  157. {
  158. var res = this.Database.SqlQuery<DbTableColumnInfo>($"PRAGMA table_info([{table}])").ToList();
  159. var entityType = entityTypes.FirstOrDefault(p => p.Name == table);
  160. if (entityType == null) continue;
  161. var entityProps = entityType.GetProperties().Where(p =>
  162. p.CanRead
  163. && p.CanWrite
  164. && !p.GetMethod.IsVirtual
  165. && p.GetCustomAttribute<NotMappedAttribute>() == null);
  166. foreach (var prop in entityProps)
  167. {
  168. var find = res.Find(p => p.name.ToLower() == prop.Name.ToLower());
  169. if (find == null)
  170. {
  171. string typeStr = "";
  172. var type = prop.PropertyType;
  173. if (prop.PropertyType.IsGenericType)
  174. {
  175. type = prop.PropertyType.GenericTypeArguments[0];
  176. }
  177. if (type == typeof(string))
  178. {
  179. typeStr = "nvarchar";
  180. }
  181. else if (type == typeof(int) || type == typeof(long) || prop.PropertyType.IsEnum)
  182. {
  183. typeStr = "int";
  184. }
  185. else if (type == typeof(double) || type == typeof(float))
  186. {
  187. typeStr = "float";
  188. }
  189. else if (type == typeof(DateTime))
  190. {
  191. typeStr = "datetime";
  192. }
  193. else if (type == typeof(bool))
  194. {
  195. typeStr = "int";
  196. }
  197. bool isNullable = prop.PropertyType.IsGenericType && prop.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>);
  198. string updateTableSql;
  199. if (isNullable)
  200. updateTableSql = $"alter table {table} add column {prop.Name} {typeStr}";
  201. else
  202. {
  203. if (typeStr == "int" || typeStr == "float")
  204. updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default 0";
  205. else if (typeStr == "nvarchar")
  206. updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default ''";
  207. else if (typeStr == "datetime")
  208. updateTableSql = $"alter table {table} add column {prop.Name} {typeStr} not null default '{DateTime.Now:yyyy-MM-dd HH:mm:ss}'";
  209. else
  210. updateTableSql = $"alter table {table} add column {prop.Name} {typeStr}";
  211. }
  212. this.Database.ExecuteSqlCommand(updateTableSql);
  213. }
  214. }
  215. }
  216. }
  217. }
  218. }