Data.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Threading.Tasks;
  6. using Vit.Core.Util.ConfigurationManager;
  7. using Vit.Core.Util.Reflection;
  8. using Vit.Linq;
  9. using Vitorm.DataProvider;
  10. using Vitorm.Entity;
  11. namespace Vitorm
  12. {
  13. public partial class Data
  14. {
  15. static Data()
  16. {
  17. #region #1 load dataProvider
  18. {
  19. var dataSourceConfigs = Appsettings.json.GetByPath<List<Dictionary<string, object>>>("Vitorm.Data");
  20. var dataProviders = dataSourceConfigs?.Select(CreateDataProvider).NotNull().ToList();
  21. if (dataProviders?.Any() == true) providerCache.AddRange(dataProviders);
  22. }
  23. #endregion
  24. #region #2 load entityLoader from appsettings.json
  25. {
  26. var configs = Appsettings.json.GetByPath<List<Dictionary<string, object>>>("Vitorm.EntityLoader");
  27. configs?.ForEach(config =>
  28. {
  29. object temp;
  30. string className = config.TryGetValue("className", out temp) ? temp as string : null;
  31. string assemblyFile = config.TryGetValue("assemblyFile", out temp) ? temp as string : null;
  32. string assemblyName = config.TryGetValue("assemblyName", out temp) ? temp as string : null;
  33. int index = config.TryGetValue("index", out temp) && temp is int i ? i : 0;
  34. var entityLoader = ObjectLoader.CreateInstance(className, assemblyFile: assemblyFile, assemblyName: assemblyName) as IEntityLoader;
  35. if (entityLoader == null) return;
  36. EntityLoaders.Instance.loaders.Insert(index, entityLoader);
  37. });
  38. }
  39. #endregion
  40. }
  41. public static bool AddDataSource(Dictionary<string, object> dataSourceConfig)
  42. {
  43. var provider = CreateDataProvider(dataSourceConfig);
  44. if (provider == null) return false;
  45. providerCache.Insert(0, provider);
  46. providerMap.Clear();
  47. return true;
  48. }
  49. public static void ClearDataSource(Predicate<DataProviderCache> predicate = null)
  50. {
  51. if (predicate != null)
  52. providerCache.RemoveAll(predicate);
  53. else
  54. providerCache.Clear();
  55. providerMap.Clear();
  56. }
  57. #region LoadDataProvider
  58. public static IDataProvider DataProvider<Entity>() => DataProvider(typeof(Entity));
  59. public static IDataProvider DataProvider(Type entityType)
  60. {
  61. return providerMap.GetOrAdd(entityType, GetDataProviderFromConfig);
  62. static IDataProvider GetDataProviderFromConfig(Type entityType)
  63. {
  64. var classFullName = entityType.FullName;
  65. return providerCache.FirstOrDefault(cache => cache.Match(classFullName))?.dataProvider
  66. ?? throw new NotImplementedException("can not find config for type: " + classFullName);
  67. }
  68. }
  69. /// <summary>
  70. /// dataProviderName: dataProviderName or dataProviderNamespace
  71. /// </summary>
  72. /// <param name="dataProviderName"></param>
  73. /// <returns></returns>
  74. public static IDataProvider DataProvider(string dataProviderName)
  75. {
  76. return providerCache.FirstOrDefault(cache => cache.name == dataProviderName || cache.@namespace == dataProviderName)?.dataProvider;
  77. }
  78. static readonly ConcurrentDictionary<Type, IDataProvider> providerMap = new();
  79. static readonly List<DataProviderCache> providerCache = new();
  80. static DataProviderCache CreateDataProvider(Dictionary<string, object> dataSourceConfig)
  81. {
  82. /*
  83. "provider": "Vitorm.Sqlite.DataProvider",
  84. "assemblyName": "Vitorm.Sqlite",
  85. "assemblyFile": "Vitorm.Sqlite.dll",
  86. */
  87. object temp;
  88. string provider = dataSourceConfig.TryGetValue("provider", out temp) ? temp as string : null;
  89. string assemblyName = dataSourceConfig.TryGetValue("assemblyName", out temp) ? temp as string : null;
  90. string assemblyFile = dataSourceConfig.TryGetValue("assemblyFile", out temp) ? temp as string : null;
  91. Type providerType;
  92. IDataProvider dataProvider;
  93. // #1 load
  94. providerType = ObjectLoader.GetType(className: provider, assemblyName: assemblyName, assemblyFile: assemblyFile);
  95. dataProvider = providerType?.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }) as IDataProvider;
  96. // #2 try load by database type (Sqlite/MySql/SqlServer)
  97. if (dataProvider == null)
  98. {
  99. providerType = ObjectLoader.GetType(className: $"Vitorm.{provider}.DataProvider", assemblyName: $"Vitorm.{provider}", assemblyFile: $"Vitorm.{provider}.dll");
  100. dataProvider = providerType?.GetConstructor(Type.EmptyTypes)?.Invoke(new object[] { }) as IDataProvider;
  101. }
  102. if (dataProvider == null) return null;
  103. dataProvider.Init(dataSourceConfig);
  104. return new DataProviderCache(dataProvider, dataSourceConfig);
  105. }
  106. #endregion
  107. #region CRUD Sync
  108. // #0 Schema : TryCreateTable TryDropTable
  109. public static void TryCreateTable<Entity>() => DataProvider<Entity>().TryCreateTable<Entity>();
  110. public static void TryDropTable<Entity>() => DataProvider<Entity>().TryDropTable<Entity>();
  111. public static void Truncate<Entity>() => DataProvider<Entity>().Truncate<Entity>();
  112. // #1 Create : Add AddRange
  113. public static Entity Add<Entity>(Entity entity) => DataProvider<Entity>().Add<Entity>(entity);
  114. public static void AddRange<Entity>(IEnumerable<Entity> entities) => DataProvider<Entity>().AddRange<Entity>(entities);
  115. // #2 Retrieve : Get Query
  116. public static Entity Get<Entity>(object keyValue) => DataProvider<Entity>().Get<Entity>(keyValue);
  117. public static IQueryable<Entity> Query<Entity>() => DataProvider<Entity>().Query<Entity>();
  118. // #3 Update: Update UpdateRange
  119. public static int Update<Entity>(Entity entity) => DataProvider<Entity>().Update<Entity>(entity);
  120. public static int UpdateRange<Entity>(IEnumerable<Entity> entities) => DataProvider<Entity>().UpdateRange<Entity>(entities);
  121. // #4 Delete : Delete DeleteRange DeleteByKey DeleteByKeys
  122. public static int Delete<Entity>(Entity entity) => DataProvider<Entity>().Delete<Entity>(entity);
  123. public static int DeleteRange<Entity>(IEnumerable<Entity> entities) => DataProvider<Entity>().DeleteRange<Entity>(entities);
  124. public static int DeleteByKey<Entity>(object keyValue) => DataProvider<Entity>().DeleteByKey<Entity>(keyValue);
  125. public static int DeleteByKeys<Entity, Key>(IEnumerable<Key> keys) => DataProvider<Entity>().DeleteByKeys<Entity, Key>(keys);
  126. #endregion
  127. #region CRUD Async
  128. // #0 Schema : TryCreateTable TryDropTable
  129. public static Task TryCreateTableAsync<Entity>() => DataProvider<Entity>().TryCreateTableAsync<Entity>();
  130. public static Task TryDropTableAsync<Entity>() => DataProvider<Entity>().TryDropTableAsync<Entity>();
  131. public static Task TruncateAsync<Entity>() => DataProvider<Entity>().TruncateAsync<Entity>();
  132. // #1 Create : Add AddRange
  133. public static Task<Entity> AddAsync<Entity>(Entity entity) => DataProvider<Entity>().AddAsync<Entity>(entity);
  134. public static Task AddRangeAsync<Entity>(IEnumerable<Entity> entities) => DataProvider<Entity>().AddRangeAsync<Entity>(entities);
  135. // #2 Retrieve : Get Query
  136. public static Task<Entity> GetAsync<Entity>(object keyValue) => DataProvider<Entity>().GetAsync<Entity>(keyValue);
  137. // #3 Update: Update UpdateRange
  138. public static Task<int> UpdateAsync<Entity>(Entity entity) => DataProvider<Entity>().UpdateAsync<Entity>(entity);
  139. public static Task<int> UpdateRangeAsync<Entity>(IEnumerable<Entity> entities) => DataProvider<Entity>().UpdateRangeAsync<Entity>(entities);
  140. // #4 Delete : Delete DeleteRange DeleteByKey DeleteByKeys
  141. public static Task<int> DeleteAsync<Entity>(Entity entity) => DataProvider<Entity>().DeleteAsync<Entity>(entity);
  142. public static Task<int> DeleteRangeAsync<Entity>(IEnumerable<Entity> entities) => DataProvider<Entity>().DeleteRangeAsync<Entity>(entities);
  143. public static Task<int> DeleteByKeyAsync<Entity>(object keyValue) => DataProvider<Entity>().DeleteByKeyAsync<Entity>(keyValue);
  144. public static Task<int> DeleteByKeysAsync<Entity, Key>(IEnumerable<Key> keys) => DataProvider<Entity>().DeleteByKeysAsync<Entity, Key>(keys);
  145. #endregion
  146. }
  147. }