Sql.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. using System.Collections;
  2. using System.Reflection;
  3. using EasyTemplate.Tool.Entity;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using SqlSugar;
  6. namespace EasyTemplate.Tool;
  7. public static class Sql
  8. {
  9. /// <summary>
  10. /// SqlSugar 上下文初始化
  11. /// </summary>
  12. /// <param name="services"></param>
  13. public static void AddSqlSugar(this IServiceCollection services)
  14. {
  15. var scope = Connect();
  16. services.AddSingleton<ISqlSugarClient>(scope);//单例注册
  17. services.AddScoped(typeof(SqlSugarRepository<>)); //仓储注册
  18. //初始化数据库表结构及种子数据
  19. InitDatabase(scope);
  20. }
  21. /// <summary>
  22. /// 初始化数据库
  23. /// </summary>
  24. /// <param name="db"></param>
  25. /// <param name="config"></param>
  26. public static void InitDatabase(SqlSugarScope db)
  27. {
  28. StaticConfig.CodeFirst_MySqlCollate = "utf8mb4_unicode_ci";
  29. db.DbMaintenance.CreateDatabase();
  30. var sugar_tables = Assembly.GetExecutingAssembly()
  31. .GetTypes()
  32. .Where(type => type.GetCustomAttributes<SugarTable>().Any());
  33. var create_seed = Setting.Get<bool>("dbConnection:connectionConfigs:0:seedSettings:enableInitSeed");
  34. foreach (var sugar_table in sugar_tables)
  35. {
  36. db.CodeFirst.InitTables(sugar_table);
  37. if (create_seed)
  38. {
  39. CreateSeedData(sugar_table, db);
  40. }
  41. }
  42. }
  43. /// <summary>
  44. /// 连接数据库并获取实例
  45. /// </summary>
  46. /// <returns></returns>
  47. public static SqlSugarScope Connect()
  48. {
  49. var enableUnderLine = Setting.Get<bool>("DbConnection:ConnectionConfigs:0:DbSettings:EnableUnderLine");
  50. var dbtypeString = Setting.Get<string>("dbConnection:connectionConfigs:0:dbType");
  51. if (!Enum.TryParse(dbtypeString, true, out DbType dbtype))
  52. {
  53. throw new ArgumentException($"无效的数据库类型: {dbtypeString}");
  54. }
  55. var option = new ConnectionConfig()
  56. {
  57. ConfigId = Global.ConfigId,
  58. //ConnectionString = "Data Source=localhost;Port=3306;Initial Catalog=the_manage_system;Persist Security Info=True;User ID=root;Password=123456;Pooling=True;charset=utf8mb4;MAX Pool Size=200;Min Pool Size=1;Connection Lifetime=30;AllowLoadLocalInfile=true;", //Global.connectionString,Data Source=filename;
  59. ConnectionString = Global.ConnectionString,
  60. DbType = dbtype,
  61. InitKeyType = InitKeyType.Attribute,
  62. IsAutoCloseConnection = true,
  63. ConfigureExternalServices = new ConfigureExternalServices
  64. {
  65. EntityNameService = (type, entity) => //处理表
  66. {
  67. entity.IsDisabledDelete = true; //禁止删除非sqlsugar创建的列
  68. //只处理贴了特性[SugarTable]表
  69. if (!type.GetCustomAttributes<SugarTable>().Any())
  70. {
  71. return;
  72. }
  73. if (enableUnderLine && !entity.DbTableName.Contains('_'))
  74. {
  75. entity.DbTableName = UtilMethods.ToUnderLine(entity.DbTableName); //驼峰转下划线
  76. }
  77. },
  78. EntityService = (type, column) => //处理列
  79. {
  80. if (!string.IsNullOrWhiteSpace(column.DbColumnName))
  81. {
  82. if (enableUnderLine && !column.DbColumnName.Contains('_'))
  83. {
  84. column.DbColumnName = UtilMethods.ToUnderLine(column.DbColumnName); //驼峰转下划线
  85. }
  86. //只处理贴了特性[SugarColumn]列
  87. if (!type.GetCustomAttributes<SugarColumn>().Any())
  88. {
  89. return;
  90. }
  91. if (new NullabilityInfoContext().Create(type).WriteState is NullabilityState.Nullable)
  92. {
  93. column.IsNullable = true;
  94. }
  95. }
  96. }
  97. },
  98. };
  99. var scope = new SqlSugarScope(option, db =>
  100. {
  101. db.Aop.DataExecuting = (oldValue, entityInfo) =>
  102. {
  103. switch (entityInfo.OperationType)
  104. {
  105. case DataFilterType.UpdateByObject:
  106. {
  107. if (entityInfo.PropertyName == nameof(EntityBase.UpdateTime))
  108. entityInfo.SetValue(DateTime.Now);
  109. else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserId))
  110. {
  111. var updateUserId = ((dynamic)entityInfo.EntityValue).UpdateUserId;
  112. if (updateUserId == null)
  113. {
  114. var value = Global.UserId > 0 ? Global.UserId : 1;
  115. entityInfo.SetValue(value);
  116. }
  117. }
  118. }
  119. break;
  120. case DataFilterType.InsertByObject:
  121. {
  122. if (entityInfo.PropertyName == nameof(EntityBase.CreateTime))
  123. entityInfo.SetValue(DateTime.Now);
  124. else if (entityInfo.PropertyName == nameof(EntityBase.CreateUserId))
  125. {
  126. var createUserId = ((dynamic)entityInfo.EntityValue).CreateUserId;
  127. if (createUserId == null)
  128. {
  129. var value = Global.UserId > 0 ? Global.UserId : 1;
  130. entityInfo.SetValue(value);
  131. }
  132. }
  133. }
  134. break;
  135. default:
  136. case DataFilterType.DeleteByObject:
  137. break;
  138. }
  139. };
  140. db.QueryFilter.AddTableFilter<IDeletedFilter>(u => u.IsDelete == false);
  141. });
  142. return scope;
  143. }
  144. /// <summary>
  145. /// 创建种子数据
  146. /// </summary>
  147. /// <param name="sugar_table"></param>
  148. /// <returns></returns>
  149. public static bool CreateSeedData(Type sugar_table, SqlSugarScope db)
  150. {
  151. try
  152. {
  153. var type = Type.GetType($"{sugar_table.Namespace}.{sugar_table.Name}SeedData");
  154. if (type != null)
  155. {
  156. var instance = Activator.CreateInstance(type);
  157. var hasDataMethod = type.GetMethod("Generate");
  158. var seedData = ((IEnumerable)hasDataMethod?.Invoke(instance, null))?.Cast<object>();
  159. if (seedData != null)
  160. {
  161. var entityType = type.GetInterfaces().First().GetGenericArguments().First();
  162. var entityInfo = db.EntityMaintenance.GetEntityInfo(entityType);
  163. if (entityInfo.Columns.Any(u => u.IsIdentity))
  164. {
  165. //按主键进行批量增加和更新
  166. var storage = db.StorageableByObject(seedData.ToList()).ToStorage();
  167. storage.AsInsertable.ExecuteCommand();
  168. storage.AsUpdateable.ExecuteCommand();
  169. }
  170. else
  171. {
  172. // 无主键则只进行插入
  173. if (!db.Queryable(entityInfo.DbTableName, entityInfo.DbTableName).Any())
  174. {
  175. db.InsertableByObject(seedData.ToList()).ExecuteCommand();
  176. }
  177. }
  178. }
  179. }
  180. return true;
  181. }
  182. catch (Exception ex)
  183. {
  184. Log.Error(ex);
  185. return false;
  186. }
  187. }
  188. /// <summary>
  189. /// 仓储假删除
  190. /// </summary>
  191. /// <typeparam name="T"></typeparam>
  192. /// <param name="db"></param>
  193. /// <param name="entity"></param>
  194. /// <returns></returns>
  195. public static bool FakeDelete<T>(this ISqlSugarClient db, T entity) where T : EntityBase, new()
  196. {
  197. return db.Updateable(entity).ReSetValue(x => { x.IsDelete = true; })
  198. .IgnoreColumns(ignoreAllNullColumns: true)
  199. .UpdateColumns(x => new { x.IsDelete, x.UpdateTime, x.UpdateUserId }, true) //允许更新的字段-AOP拦截自动设置UpdateTime、UpdateUserId
  200. .ExecuteCommand() > 0;
  201. }
  202. /// <summary>
  203. /// 仓储假删除
  204. /// </summary>
  205. /// <typeparam name="T"></typeparam>
  206. /// <param name="db"></param>
  207. /// <param name="entity"></param>
  208. /// <returns></returns>
  209. public static async Task<bool> FakeDeleteAsync<T>(this ISqlSugarClient db, T entity) where T : EntityBase, new()
  210. {
  211. return await db.Updateable(entity).ReSetValue(x => { x.IsDelete = true; })
  212. .IgnoreColumns(ignoreAllNullColumns: true)
  213. .UpdateColumns(x => x.IsDelete, true) //允许更新的字段-AOP拦截自动设置UpdateTime、UpdateUserId
  214. .ExecuteCommandAsync() > 0;
  215. }
  216. }
  217. public class SqlSugarRepository<T> : SimpleClient<T> where T : class, new()
  218. {
  219. public SqlSugarRepository(ISqlSugarClient db)
  220. {
  221. //var iTenant = Sql.ITenant;
  222. ////若实体贴有系统表特性,则返回默认库连接
  223. //if (typeof(T).IsDefined(typeof(MainTableAttribute), false))
  224. //{
  225. // base.Context = iTenant.GetConnectionScope(Global.mainConfigId);
  226. // return;
  227. //}
  228. //if (typeof(T).IsDefined(typeof(SubTableAttribute), false))
  229. //{
  230. // if (!iTenant.IsAnyConnection(Global.subConfigId))
  231. // {
  232. // var aaa = 1;
  233. // }
  234. // base.Context = iTenant.GetConnectionScope(Global.subConfigId);
  235. // return;
  236. //}
  237. base.Context = db;
  238. }
  239. }
  240. /// <summary>
  241. /// 主表
  242. /// </summary>
  243. [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
  244. public class MainTableAttribute : Attribute
  245. {
  246. }
  247. /// <summary>
  248. /// 子表
  249. /// </summary>
  250. [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
  251. public class SubTableAttribute : Attribute
  252. {
  253. }