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.

399 lines
15 KiB

4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
3 years ago
3 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
3 years ago
4 years ago
  1. using Apewer.Internals;
  2. using Newtonsoft.Json.Linq;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Data;
  6. using static Apewer.TextUtility;
  7. namespace Apewer.Source
  8. {
  9. /// <summary>System.Data.DataTable 装箱查询。</summary>
  10. public sealed class Query : IQuery, IDisposable, IToJson
  11. {
  12. private bool _disposed = false;
  13. private bool _success = false;
  14. private string _message = null;
  15. private DataTable _table = null;
  16. private DataTable[] _tables = null;
  17. /// <summary>创建实例,默认状态为失败。</summary>
  18. public Query(bool success = false, string message = null)
  19. {
  20. _success = false;
  21. _message = message;
  22. }
  23. /// <summary>创建实例,Exception 为 NULL 时成功,非 NULL 时失败。</summary>
  24. public Query(Exception exception)
  25. {
  26. _success = exception == null;
  27. _message = RuntimeUtility.Message(exception);
  28. }
  29. /// <summary>创建实例,包装一个 DataTable 对象,数据表为 NULL 时失败,非 NULL 时成功。</summary>
  30. public Query(DataTable table)
  31. {
  32. _table = table;
  33. _success = table != null;
  34. _message = table == null ? "未获取有效的数据表。" : null;
  35. }
  36. /// <summary>创建实例,包装一个 DataTable 对象。</summary>
  37. public Query(DataTable table, bool success, string message = null)
  38. {
  39. _table = table;
  40. _success = success;
  41. _message = message;
  42. }
  43. /// <summary>创建实例,包装多个 DataTable 对象。</summary>
  44. public Query(DataTable[] tables, bool success = true, string message = null)
  45. {
  46. _tables = tables;
  47. _success = success;
  48. _message = message;
  49. if (tables != null && tables.Length > 0) _table = tables[0];
  50. }
  51. /// <summary>从 <see cref="Query"/> 到 <see cref="Boolean"/> 的隐式转换,判断 <see cref="Query"/> 执行成功且包含表。</summary>
  52. public static implicit operator bool(Query query) => query != null && query.Success && query.Table != null;
  53. /// <summary>从 <see cref="DataTable"/> 到 <see cref="Query"/> 的隐式转换。</summary>
  54. public static implicit operator Query(DataTable table) => new Query(table, table != null, null);
  55. /// <summary>从 <see cref="Query"/> 到 <see cref="DataTable"/> 的隐式转换。</summary>
  56. public static implicit operator DataTable(Query query) => query?.Table;
  57. #region Property
  58. /// <summary>语句执行成功。</summary>
  59. public bool Success { get => _success; }
  60. /// <summary>消息。</summary>
  61. public string Message { get => _message; }
  62. /// <summary>所有结果表。</summary>
  63. public DataTable[] Tables { get => _tables; }
  64. /// <summary>获取默认结果表。如果设置默认结果表,会丢失设置前的所有结果表。</summary>
  65. public DataTable Table { get => _table; }
  66. /// <summary>默认表中的数据总行数。</summary>
  67. public int Rows { get => _table == null ? 0 : _table.Rows.Count; }
  68. /// <summary>默认表中的数据总列数。</summary>
  69. public int Columns { get => _table == null ? 0 : _table.Columns.Count; }
  70. #endregion
  71. #region Value
  72. /// <summary>获取默认表中第 0 行、第 0 列的单元格内容。</summary>
  73. public object Value()
  74. {
  75. if (_disposed) return null;
  76. return Value(0, 0);
  77. }
  78. /// <summary>获取默认表中指定行中第 0 列的内容。</summary>
  79. /// <param name="rowIndex">行索引,从 0 开始。</param>
  80. public object Value(int rowIndex)
  81. {
  82. if (_disposed) return null;
  83. return Value(rowIndex, 0);
  84. }
  85. /// <summary>获取默认表中第 0 行指定列的内容。</summary>
  86. /// <param name="columnName">列名称/字段名称,此名称不区分大小写。</param>
  87. public object Value(string columnName)
  88. {
  89. if (_disposed) return null;
  90. return Value(0, columnName);
  91. }
  92. /// <summary>获取默认表中指定单元格的内容。</summary>
  93. /// <param name="rowIndex">行索引,从 0 开始。</param>
  94. /// <param name="columnIndex">列索引,从 0 开始。</param>
  95. public object Value(int rowIndex, int columnIndex)
  96. {
  97. if (_disposed) return null;
  98. if (_table != null)
  99. {
  100. if (rowIndex >= 0 && rowIndex < _table.Rows.Count)
  101. {
  102. if (columnIndex >= 0 && columnIndex < _table.Columns.Count)
  103. {
  104. var value = _table.Rows[rowIndex][columnIndex];
  105. if (value == null || value.Equals(DBNull.Value)) return null;
  106. return value;
  107. }
  108. }
  109. }
  110. return null;
  111. }
  112. /// <summary>获取默认表中指定单元的内容。</summary>
  113. /// <param name="rowIndex">行索引,从 0 开始。</param>
  114. /// <param name="columnName">列名称/字段名称,此名称不区分大小写。</param>
  115. public object Value(int rowIndex, string columnName)
  116. {
  117. if (_disposed) return null;
  118. if ((Table != null) && !string.IsNullOrEmpty(columnName))
  119. {
  120. if ((rowIndex < Table.Rows.Count) && (rowIndex >= 0))
  121. {
  122. try
  123. {
  124. var value = Table.Rows[rowIndex][columnName];
  125. if (value == null || value.Equals(DBNull.Value)) return null;
  126. return value;
  127. }
  128. catch { }
  129. }
  130. }
  131. return null;
  132. }
  133. /// <summary>搜索默认表。</summary>
  134. /// <param name="conditionColumn">搜索条件:列名。</param>
  135. /// <param name="conditionValue">搜索条件:列值。</param>
  136. /// <param name="resultColumn">搜索结果。</param>
  137. private object Value(string conditionColumn, string conditionValue, string resultColumn)
  138. {
  139. if (_disposed) return null;
  140. if ((Table != null) && (!string.IsNullOrEmpty(conditionColumn)) && (conditionValue != null) && (!string.IsNullOrEmpty(resultColumn)))
  141. {
  142. for (int i = 0; i < Table.Rows.Count; i++)
  143. {
  144. try
  145. {
  146. var cValue = Table.Rows[i][conditionColumn];
  147. if (cValue == null || cValue.Equals(DBNull.Value)) cValue = null;
  148. if (cValue.ToString() == conditionValue) return Table.Rows[i][resultColumn];
  149. }
  150. catch { }
  151. }
  152. }
  153. return null;
  154. }
  155. /// <summary>搜索默认表。</summary>
  156. /// <param name="conditionColumn">搜索条件:列名。</param>
  157. /// <param name="conditionValue">搜索条件:列值。</param>
  158. /// <param name="resultColumn">搜索结果的列名。</param>
  159. private object Value(int conditionColumn, string conditionValue, int resultColumn)
  160. {
  161. if (_disposed) return null;
  162. if ((Table != null) && (conditionColumn >= 0) && (conditionValue != null) && (resultColumn >= 0))
  163. {
  164. if ((conditionColumn < Table.Columns.Count) && (resultColumn < Table.Columns.Count))
  165. {
  166. for (int i = 0; i < Table.Rows.Count; i++)
  167. {
  168. try
  169. {
  170. var cValue = Table.Rows[i][conditionColumn];
  171. if (cValue == null || cValue.Equals(DBNull.Value)) cValue = null;
  172. if (cValue.ToString() == conditionValue) return Table.Rows[i][resultColumn];
  173. }
  174. catch { }
  175. }
  176. }
  177. }
  178. return null;
  179. }
  180. #endregion
  181. #region Method
  182. /// <summary>搜索默认表。</summary>
  183. /// <param name="conditionColumn">搜索条件:列名。</param>
  184. /// <param name="conditionValue">搜索条件:列值。</param>
  185. /// <param name="resultColumn">搜索结果。</param>
  186. private string Text(int conditionColumn, string conditionValue, int resultColumn)
  187. {
  188. var value = Value(conditionColumn, conditionValue, resultColumn);
  189. return Text(value);
  190. }
  191. /// <summary>释放系统资源。</summary>
  192. public void Dispose()
  193. {
  194. if (_disposed) return;
  195. if (_tables != null)
  196. {
  197. foreach (var table in _tables) RuntimeUtility.Dispose(table);
  198. _tables = null;
  199. }
  200. RuntimeUtility.Dispose(_table);
  201. _table = null;
  202. _tables = null;
  203. _disposed = true;
  204. // GC.SuppressFinalize(this);
  205. }
  206. /// <summary>当不指定格式化程序时,自动根据类型选择预置的格式化程序。</summary>
  207. private static Func<object, T> GetValueFormatter<T>()
  208. {
  209. var type = typeof(T);
  210. if (type.Equals(typeof(string))) return TextFormatter<T>;
  211. else return ForceFormatter<T>;
  212. }
  213. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  214. public T[] ReadColumn<T>(int column = 0, Func<object, T> formatter = null) => SourceUtility.Column(this, (r) => (formatter ?? GetValueFormatter<T>()).Invoke(Value(r, column)));
  215. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  216. /// <exception cref="ArgumentNullException"></exception>
  217. public T[] ReadColumn<T>(string column, Func<object, T> formatter = null) => SourceUtility.Column(this, (r) => (formatter ?? GetValueFormatter<T>()).Invoke(Value(r, column)));
  218. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  219. public string[] ReadColumn(int column = 0) => SourceUtility.Column(this, (r) => this.Text(r, column));
  220. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  221. /// <exception cref="ArgumentNullException"></exception>
  222. public string[] ReadColumn(string column) => SourceUtility.Column(this, (r) => this.Text(r, column));
  223. #endregion
  224. #region 模型化、IToJson
  225. /// <summary>转换为 Json 对象。</summary>
  226. public Json ToJson()
  227. {
  228. var columns = Json.NewArray();
  229. var rows = Json.NewArray();
  230. var table = _table;
  231. if (!_disposed && table != null)
  232. {
  233. var columnsCount = table.Columns.Count;
  234. for (var c = 0; c < columnsCount; c++)
  235. {
  236. var dc = table.Columns[c];
  237. var column = Json.NewObject();
  238. column.SetProperty("name", dc.ColumnName);
  239. column.SetProperty("type", dc.DataType.FullName);
  240. columns.AddItem(column);
  241. }
  242. var rowsCount = table.Rows.Count;
  243. for (var r = 0; r < rowsCount; r++)
  244. {
  245. var row = Json.NewArray();
  246. for (var c = 0; c < columnsCount; c++)
  247. {
  248. var v = Value(r, c);
  249. if (v == null) row.AddItem();
  250. else if (v.Equals(DBNull.Value)) row.AddItem();
  251. else if (v is byte vByte) row.AddItem(vByte);
  252. else if (v is short vInt16) row.AddItem(vInt16);
  253. else if (v is int vInt32) row.AddItem(vInt32);
  254. else if (v is long vInt64) row.AddItem(vInt64);
  255. else if (v is float vSingle) row.AddItem(vSingle);
  256. else if (v is double vDouble) row.AddItem(vDouble);
  257. else if (v is decimal vDecimal) row.AddItem(vDecimal);
  258. else if (v is bool vBoolean) row.AddItem(vBoolean);
  259. else if (v is byte[] vBytes) row.AddItem(vBytes.Base64());
  260. else if (v is DateTime vDateTime) row.AddItem(vDateTime.Lucid());
  261. else row.AddItem(v.ToString());
  262. }
  263. rows.AddItem(row);
  264. }
  265. }
  266. var jsonObject = Json.NewObject();
  267. jsonObject.SetProperty("success", _success);
  268. jsonObject.SetProperty("message", _message);
  269. jsonObject.SetProperty("columns", columns);
  270. jsonObject.SetProperty("rows", rows);
  271. return jsonObject;
  272. }
  273. /// <summary>转换为模型数组。</summary>
  274. public ObjectSet[] ToArray()
  275. {
  276. var oss = null as ObjectSet[];
  277. var table = _table;
  278. if (!_disposed && table != null)
  279. {
  280. var width = table.Columns.Count;
  281. var names = new string[width];
  282. for (var c = 0; c < width; c++)
  283. {
  284. var name = table.Columns[c].ColumnName;
  285. if (name.IsEmpty()) continue;
  286. if (names.Contains(name)) continue;
  287. names[c] = name;
  288. }
  289. var unnamed = 1;
  290. for (var c = 0; c < width; c++)
  291. {
  292. if (names[c] != null) continue;
  293. while (true)
  294. {
  295. var name = "unnamed_" + unnamed.ToString();
  296. unnamed++;
  297. if (names.Contains(name)) continue;
  298. names[c] = name;
  299. break;
  300. }
  301. }
  302. var height = table.Rows.Count;
  303. oss = new ObjectSet[height];
  304. for (var r = 0; r < height; r++)
  305. {
  306. var os = new ObjectSet();
  307. var dict = os.Origin;
  308. for (var c = 0; c < width; c++)
  309. {
  310. var v = Value(r, c);
  311. dict.Add(names[c], v.IsNull() ? null : v);
  312. }
  313. oss[r] = os;
  314. }
  315. }
  316. return oss;
  317. }
  318. #endregion
  319. #region Static
  320. private static T ForceFormatter<T>(object input) => (T)input;
  321. private static T TextFormatter<T>(object input) => (T)(Text(input) as object);
  322. private static ObjectDisposedException DisposedException { get { return new ObjectDisposedException(typeof(Query).FullName); } }
  323. #endregion
  324. #region Extension
  325. internal static string Text(object value)
  326. {
  327. if (value == null) return null;
  328. if (value is string str) return str;
  329. try { return value.ToString() ?? ""; } catch { }
  330. return "";
  331. }
  332. internal static Class<DateTime> DateTime(object value)
  333. {
  334. if (value is DateTime dt) return dt;
  335. DateTime result;
  336. var parsed = System.DateTime.TryParse(value.ToString(), out result);
  337. return parsed ? new Class<DateTime>(result) : null;
  338. }
  339. #endregion
  340. }
  341. }