StorageableDataTable.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace SqlSugar
  8. {
  9. public class StorageableDataTable
  10. {
  11. internal DataTable DataTable { get; set; }
  12. internal SqlSugarProvider Context { get; set; }
  13. internal string[] Columns { get; set; } = new string[] { };
  14. internal string SugarGroupId = "SugarGroupId";
  15. internal string SugarUpdateRows = "SugarUpdateRows";
  16. internal string SugarColumns = "SugarColumns";
  17. internal string SugarErrorMessage = "SugarErrorMessage";
  18. internal List<DataRow> dbDataList = new List<DataRow>();
  19. List<KeyValuePair<StorageType, Func<DataRow, bool>,string>> whereFuncs = new List<KeyValuePair<StorageType, Func<DataRow, bool>,string>>();
  20. public StorageableDataTable WhereColumns(string name)
  21. {
  22. return WhereColumns(new string[] { name});
  23. }
  24. public StorageableDataTable WhereColumns(string[] names)
  25. {
  26. this.Columns = names;
  27. var queryable = this.Context.Queryable<object>();
  28. Check.Exception(Columns==null|| Columns.Length==0,"need WhereColums");
  29. var tableName = queryable.SqlBuilder.GetTranslationTableName(DataTable.TableName);
  30. this.Context.Utilities.PageEach(DataTable.Rows.Cast<DataRow>(), 200, itemList =>
  31. {
  32. List<IConditionalModel> conditList = new List<IConditionalModel>();
  33. SetConditList(itemList, Columns, conditList);
  34. string selector = null;
  35. if (queryable.SqlBuilder.SqlParameterKeyWord == ":")
  36. {
  37. //Oracle driver bug: Error when querying DataTable after dynamically adding columns using '*'.
  38. selector = " * /*" + Guid.NewGuid() + "*/";
  39. }
  40. var addItem = this.Context.Queryable<object>().AS(tableName).Where(conditList).Select(selector).ToDataTable().Rows.Cast<DataRow>().ToList();
  41. this.dbDataList.AddRange(addItem);
  42. });
  43. return this;
  44. }
  45. public StorageableDataTable WhereColumns(List<string> names)
  46. {
  47. return WhereColumns(names.ToArray());
  48. }
  49. public StorageableDataTable SplitInsert(Func<DataRow, bool> conditions, string message = null)
  50. {
  51. whereFuncs.Add(new KeyValuePair<StorageType, Func<DataRow, bool>, string>(StorageType.Insert, conditions,message));
  52. return this;
  53. }
  54. public StorageableDataTable SplitDelete(Func<DataRow, bool> conditions, string message = null)
  55. {
  56. whereFuncs.Add(new KeyValuePair<StorageType, Func<DataRow, bool>,string>(StorageType.Delete, conditions,message));
  57. return this;
  58. }
  59. public StorageableDataTable SplitUpdate(Func<DataRow, bool> conditions, string message = null)
  60. {
  61. whereFuncs.Add(new KeyValuePair<StorageType, Func<DataRow, bool>,string>(StorageType.Update, conditions,message));
  62. return this;
  63. }
  64. public StorageableDataTable Saveable(string inserMessage = null, string updateMessage = null)
  65. {
  66. SplitUpdate(it => it.Any(), updateMessage);
  67. SplitInsert(it => true, inserMessage);
  68. return this;
  69. }
  70. public StorageableDataTable SplitError(Func<DataRow, bool> conditions, string message = null)
  71. {
  72. whereFuncs.Add(new KeyValuePair<StorageType, Func<DataRow, bool>, string>(StorageType.Error, conditions, message));
  73. return this;
  74. }
  75. public StorageableDataTable SplitIgnore(Func<DataRow, bool> conditions, string message = null)
  76. {
  77. whereFuncs.Add(new KeyValuePair<StorageType, Func<DataRow, bool>, string>(StorageType.Ignore, conditions, message));
  78. return this;
  79. }
  80. public DataTableResult ToStorage()
  81. {
  82. if (whereFuncs == null || whereFuncs.Count == 0)
  83. {
  84. Saveable();
  85. }
  86. foreach (DataRow row in DataTable.Rows)
  87. {
  88. foreach (var item in whereFuncs.OrderByDescending(it => (int)it.key))
  89. {
  90. SplitMethod(item.value1,item.key,row,item.value2);
  91. }
  92. if (row[SugarGroupId] == null || row[SugarGroupId] == DBNull.Value)
  93. {
  94. row[SugarGroupId] = StorageType.Ignore;
  95. }
  96. }
  97. DataTable.Columns.Remove(SugarUpdateRows);
  98. DataTable.Columns.Remove(SugarColumns);
  99. var Groups=DataTable.Rows.Cast<DataRow>()
  100. .Where(it=> it[SugarGroupId]!=null&& it[SugarGroupId] != DBNull.Value)
  101. .GroupBy(it => ((StorageType)it[SugarGroupId]).ToString()).Select(it=>new DataTableGroups{ Type=it.Key,DataTable= it.CopyToDataTable() })
  102. .ToList();
  103. DataTable.Columns.Remove(SugarGroupId);
  104. DataTable.Columns.Remove(SugarErrorMessage);
  105. var inserList = new List<Dictionary<string, object>>();
  106. var updateList = new List<Dictionary<string, object>>();
  107. var DeleteList=Groups.FirstOrDefault(it=>it.Type==StorageType.Delete.ToString());
  108. if (Groups.Any(it => it.Type == StorageType.Insert.ToString()))
  109. {
  110. foreach (var item in Groups)
  111. {
  112. if (item.Type == StorageType.Insert.ToString())
  113. {
  114. item.DataTable.Columns.Remove(SugarGroupId);
  115. item.DataTable.Columns.Remove(SugarErrorMessage);
  116. inserList.AddRange(this.Context.Utilities.DataTableToDictionaryList(item.DataTable));
  117. }
  118. }
  119. }
  120. if (Groups.Any(it => it.Type == StorageType.Update.ToString()))
  121. {
  122. foreach (var item in Groups)
  123. {
  124. if (item.Type == StorageType.Update.ToString())
  125. {
  126. item.DataTable.Columns.Remove(SugarGroupId);
  127. item.DataTable.Columns.Remove(SugarErrorMessage);
  128. updateList.AddRange(this.Context.Utilities.DataTableToDictionaryList(item.DataTable));
  129. }
  130. }
  131. }
  132. List<IConditionalModel> conditionalModels = new List<IConditionalModel>();
  133. if (DeleteList!=null)
  134. {
  135. SetConditList(DeleteList.DataTable.Rows.Cast<DataRow>().ToList(), Columns, conditionalModels);
  136. }
  137. var tableName = this.Context.Queryable<object>().SqlBuilder.GetTranslationTableName(DataTable.TableName);
  138. DataTableResult result = new DataTableResult()
  139. {
  140. DataTableGroups=Groups,
  141. AsDeleteable=this.Context.Deleteable<object>().AS(tableName).Where(conditionalModels),
  142. AsUpdateable= this.Context.Updateable(updateList).AS(tableName).WhereColumns(Columns),
  143. AsInsertable=this.Context.Insertable(inserList).AS(tableName)
  144. };
  145. return result;
  146. }
  147. private void SplitMethod(Func<DataRow, bool> conditions, StorageType type,DataRow item,string message)
  148. {
  149. item[SugarColumns] = Columns;
  150. item[SugarUpdateRows] = dbDataList;
  151. if ((item[SugarGroupId]==null|| item[SugarGroupId] == DBNull.Value) && conditions(item))
  152. {
  153. item[SugarGroupId] = type;
  154. item[SugarErrorMessage] = message;
  155. }
  156. }
  157. private void SetConditList(List<DataRow> itemList, string[] whereColumns, List<IConditionalModel> conditList)
  158. {
  159. ;
  160. foreach (var dataItem in itemList)
  161. {
  162. var condition = new ConditionalCollections()
  163. {
  164. ConditionalList = new List<KeyValuePair<WhereType, SqlSugar.ConditionalModel>>()
  165. };
  166. conditList.Add(condition);
  167. int i = 0;
  168. foreach (var name in whereColumns)
  169. {
  170. var value = dataItem[name];
  171. if (value != null && value.GetType().IsEnum())
  172. {
  173. value = Convert.ToInt64(value);
  174. }
  175. condition.ConditionalList.Add(new KeyValuePair<WhereType, ConditionalModel>(i == 0 ? WhereType.Or : WhereType.And, new ConditionalModel()
  176. {
  177. FieldName = name,
  178. ConditionalType = ConditionalType.Equal,
  179. FieldValue = value + "",
  180. FieldValueConvertFunc = this.Context.CurrentConnectionConfig.DbType == DbType.PostgreSQL ?
  181. UtilMethods.GetTypeConvert(value) : null
  182. }));
  183. ++i;
  184. }
  185. }
  186. }
  187. }
  188. public class DataTableResult
  189. {
  190. public List<DataTableGroups> DataTableGroups { get; set; }
  191. public IUpdateable<Dictionary<string, object>> AsUpdateable { get; set; }
  192. public IDeleteable<object> AsDeleteable { get; set; }
  193. public IInsertable<Dictionary<string, object>> AsInsertable { get; set; }
  194. }
  195. public class DataTableGroups
  196. {
  197. public string Type { get; set; }
  198. public DataTable DataTable { get; set; }
  199. }
  200. public static class StorageableDataTableExtensions
  201. {
  202. public static bool Any(this DataRow row)
  203. {
  204. var list=row["SugarUpdateRows"] as List<DataRow>;
  205. var columns = row["SugarColumns"] as string[];
  206. return list.Any(it =>
  207. {
  208. var result = true;
  209. foreach (var name in columns)
  210. {
  211. if (result)
  212. {
  213. result = row[name].ObjToString() == it[name].ObjToString();
  214. if (result==false&&it[name] != null && it[name].GetType() == UtilConstants.DecType)
  215. {
  216. result= row[name].ObjToDecimal() == it[name].ObjToDecimal();
  217. }
  218. if (result == false)
  219. {
  220. break;
  221. }
  222. }
  223. }
  224. return result;
  225. });
  226. }
  227. }
  228. }