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.

376 lines
14 KiB

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
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
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
  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 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. #region Property
  52. /// <summary>语句执行成功。</summary>
  53. public bool Success { get => _success; }
  54. /// <summary>消息。</summary>
  55. public string Message { get => _message; }
  56. /// <summary>所有结果表。</summary>
  57. public DataTable[] Tables { get => _tables; }
  58. /// <summary>获取默认结果表。如果设置默认结果表,会丢失设置前的所有结果表。</summary>
  59. public DataTable Table { get => _table; }
  60. /// <summary>默认表中的数据总行数。</summary>
  61. public int Rows { get => _table == null ? 0 : _table.Rows.Count; }
  62. /// <summary>默认表中的数据总列数。</summary>
  63. public int Columns { get => _table == null ? 0 : _table.Columns.Count; }
  64. #endregion
  65. #region Value
  66. /// <summary>获取默认表中第 0 行、第 0 列的单元格内容。</summary>
  67. public object Value()
  68. {
  69. if (_disposed) return null;
  70. return Value(0, 0);
  71. }
  72. /// <summary>获取默认表中指定行中第 0 列的内容。</summary>
  73. /// <param name="rowIndex">行索引,从 0 开始。</param>
  74. public object Value(int rowIndex)
  75. {
  76. if (_disposed) return null;
  77. return Value(rowIndex, 0);
  78. }
  79. /// <summary>获取默认表中第 0 行指定列的内容。</summary>
  80. /// <param name="columnName">列名称。</param>
  81. public object Value(string columnName)
  82. {
  83. if (_disposed) return null;
  84. return Value(0, columnName);
  85. }
  86. /// <summary>获取默认表中指定单元格的内容。</summary>
  87. /// <param name="rowIndex">行索引,从 0 开始。</param>
  88. /// <param name="columnIndex">列索引,从 0 开始。</param>
  89. public object Value(int rowIndex, int columnIndex)
  90. {
  91. if (_disposed) return null;
  92. if (_table != null)
  93. {
  94. if (rowIndex >= 0 && rowIndex < _table.Rows.Count)
  95. {
  96. if (columnIndex >= 0 && columnIndex < _table.Columns.Count)
  97. {
  98. return _table.Rows[rowIndex][columnIndex];
  99. }
  100. }
  101. }
  102. return null;
  103. }
  104. /// <summary>获取默认表中指定单元的内容。</summary>
  105. /// <param name="rowIndex">行索引,从 0 开始。</param>
  106. /// <param name="columnName">列名称。</param>
  107. public object Value(int rowIndex, string columnName)
  108. {
  109. if (_disposed) return null;
  110. if ((Table != null) && !string.IsNullOrEmpty(columnName))
  111. {
  112. if ((rowIndex < Table.Rows.Count) && (rowIndex >= 0))
  113. {
  114. try { return Table.Rows[rowIndex][columnName]; }
  115. catch { }
  116. }
  117. }
  118. return null;
  119. }
  120. /// <summary>搜索默认表。</summary>
  121. /// <param name="conditionColumn">搜索条件:列名。</param>
  122. /// <param name="conditionValue">搜索条件:列值。</param>
  123. /// <param name="resultColumn">搜索结果。</param>
  124. public object Value(string conditionColumn, string conditionValue, string resultColumn)
  125. {
  126. if (_disposed) return null;
  127. if ((Table != null) && (!string.IsNullOrEmpty(conditionColumn)) && (conditionValue != null) && (!string.IsNullOrEmpty(resultColumn)))
  128. {
  129. for (int i = 0; i < Table.Rows.Count; i++)
  130. {
  131. try
  132. {
  133. if (Table.Rows[i][conditionColumn].ToString() == conditionValue) return Table.Rows[i][resultColumn];
  134. }
  135. catch { }
  136. }
  137. }
  138. return null;
  139. }
  140. /// <summary>搜索默认表。</summary>
  141. /// <param name="conditionColumn">搜索条件:列名。</param>
  142. /// <param name="conditionValue">搜索条件:列值。</param>
  143. /// <param name="resultColumn">搜索结果的列名。</param>
  144. public object Value(int conditionColumn, string conditionValue, int resultColumn)
  145. {
  146. if (_disposed) return null;
  147. if ((Table != null) && (conditionColumn >= 0) && (conditionValue != null) && (resultColumn >= 0))
  148. {
  149. if ((conditionColumn < Table.Columns.Count) && (resultColumn < Table.Columns.Count))
  150. {
  151. for (int i = 0; i < Table.Rows.Count; i++)
  152. {
  153. try
  154. {
  155. if (Table.Rows[i][conditionColumn].ToString() == conditionValue) return Table.Rows[i][resultColumn];
  156. }
  157. catch { }
  158. }
  159. }
  160. }
  161. return null;
  162. }
  163. #endregion
  164. #region Method
  165. /// <summary>搜索默认表。</summary>
  166. /// <param name="conditionColumn">搜索条件:列名。</param>
  167. /// <param name="conditionValue">搜索条件:列值。</param>
  168. /// <param name="resultColumn">搜索结果。</param>
  169. public string Text(int conditionColumn, string conditionValue, int resultColumn)
  170. {
  171. var value = Value(conditionColumn, conditionValue, resultColumn);
  172. return Text(value);
  173. }
  174. /// <summary>释放系统资源。</summary>
  175. public virtual void Dispose()
  176. {
  177. if (_disposed) return;
  178. if (_tables != null)
  179. {
  180. foreach (var table in _tables) RuntimeUtility.Dispose(table);
  181. _tables = null;
  182. }
  183. RuntimeUtility.Dispose(_table);
  184. _table = null;
  185. _tables = null;
  186. _disposed = true;
  187. // GC.SuppressFinalize(this);
  188. }
  189. /// <summary>当不指定格式化程序时,自动根据类型选择预置的格式化程序。</summary>
  190. private static Func<object, T> GetValueFormatter<T>()
  191. {
  192. var type = typeof(T);
  193. if (type.Equals(typeof(string))) return TextFormatter<T>;
  194. else return ForceFormatter<T>;
  195. }
  196. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  197. public T[] ReadColumn<T>(int column = 0, Func<object, T> formatter = null) => OrmHelper.Column(this, (r) => (formatter ?? GetValueFormatter<T>()).Invoke(Value(r, column)));
  198. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  199. /// <exception cref="ArgumentNullException"></exception>
  200. public T[] ReadColumn<T>(string column, Func<object, T> formatter = null) => OrmHelper.Column(this, (r) => (formatter ?? GetValueFormatter<T>()).Invoke(Value(r, column)));
  201. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  202. public string[] ReadColumn(int column = 0) => OrmHelper.Column(this, (r) => this.Text(r, column));
  203. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  204. /// <exception cref="ArgumentNullException"></exception>
  205. public string[] ReadColumn(string column) => OrmHelper.Column(this, (r) => this.Text(r, column));
  206. #endregion
  207. #region IToJson
  208. /// <summary>转换为 Json 对象。</summary>
  209. public Json ToJson()
  210. {
  211. var columns = Json.NewArray();
  212. var rows = Json.NewArray();
  213. var table = _table;
  214. if (!_disposed && table != null)
  215. {
  216. var columnsCount = _table.Columns.Count;
  217. for (var c = 0; c < columnsCount; c++)
  218. {
  219. var dc = table.Columns[c];
  220. var column = Json.NewObject();
  221. column.SetProperty("name", dc.ColumnName);
  222. column.SetProperty("type", dc.DataType.FullName);
  223. columns.AddItem(column);
  224. }
  225. var rowsCount = table.Rows.Count;
  226. for (var r = 0; r < _table.Rows.Count; r++)
  227. {
  228. var row = Json.NewArray();
  229. for (var c = 0; c < columnsCount; c++)
  230. {
  231. var v = Value(r, c);
  232. if (v == null) row.AddItem();
  233. else if (v.Equals(DBNull.Value)) row.AddItem();
  234. else if (v is byte vByte) row.AddItem(vByte);
  235. else if (v is short vInt16) row.AddItem(vInt16);
  236. else if (v is int vInt32) row.AddItem(vInt32);
  237. else if (v is long vInt64) row.AddItem(vInt64);
  238. else if (v is float vSingle) row.AddItem(vSingle);
  239. else if (v is double vDouble) row.AddItem(vDouble);
  240. else if (v is decimal vDecimal) row.AddItem(vDecimal);
  241. else if (v is bool vBoolean) row.AddItem(vBoolean);
  242. else if (v is byte[] vBytes) row.AddItem(vBytes.Base64());
  243. else if (v is DateTime vDateTime) row.AddItem(vDateTime.Lucid());
  244. else row.AddItem(v.ToString());
  245. }
  246. rows.AddItem(row);
  247. }
  248. }
  249. var jsonObject = Json.NewObject();
  250. jsonObject.SetProperty("success", _success);
  251. jsonObject.SetProperty("message", _message);
  252. jsonObject.SetProperty("columns", columns);
  253. jsonObject.SetProperty("rows", rows);
  254. return jsonObject;
  255. }
  256. #endregion
  257. #region Static
  258. private static T ForceFormatter<T>(object input) => (T)input;
  259. private static T TextFormatter<T>(object input) => (T)(Text(input) as object);
  260. private static ObjectDisposedException DisposedException { get { return new ObjectDisposedException(typeof(Query).FullName); } }
  261. /// <summary>简单查询:取结果中第 0 列所有单元格的文本形式,可指定查询后关闭服务器连接,返回结果中不包含无效文本。</summary>
  262. public static string[] SimpleColumn(IDbClientAdo database, string statement, bool dispose = false)
  263. {
  264. if (database == null) return new string[0];
  265. var ab = new ArrayBuilder<string>();
  266. using (var query = database.Query(statement))
  267. {
  268. var rows = query.Rows;
  269. if (rows > 0)
  270. {
  271. var added = 0;
  272. for (int i = 0; i < rows; i++)
  273. {
  274. var cell = Trim(query.Text(i));
  275. if (string.IsNullOrEmpty(cell)) continue;
  276. ab.Add(cell);
  277. added++;
  278. }
  279. }
  280. }
  281. if (dispose) RuntimeUtility.Dispose(database);
  282. return ab.Export();
  283. }
  284. /// <summary>简单查询:取结果中第 0 行、第 0 列单元格中的文本,可指定查询后关闭服务器连接。</summary>
  285. public static string SimpleCell(IDbClientAdo database, string statement, bool dispose = false)
  286. {
  287. if (database == null) return "";
  288. var query = database.Query(statement);
  289. var cell = Trim(Query.Text(query.Value()));
  290. query.Dispose();
  291. if (dispose) RuntimeUtility.Dispose(database);
  292. return cell;
  293. }
  294. #endregion
  295. #region Extension
  296. internal static string Text(object value)
  297. {
  298. var result = Constant.EmptyString;
  299. if (value != null)
  300. {
  301. if (!value.Equals(DBNull.Value))
  302. {
  303. try
  304. {
  305. result = value.ToString();
  306. }
  307. finally { }
  308. }
  309. }
  310. return result;
  311. }
  312. internal static Class<DateTime> DateTime(object value)
  313. {
  314. if (value == null) return null;
  315. if (value is DateTime) return null;
  316. DateTime result;
  317. var parsed = System.DateTime.TryParse(value.ToString(), out result);
  318. return parsed ? new Class<DateTime>(result) : null;
  319. }
  320. #endregion
  321. }
  322. }