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.

631 lines
22 KiB

  1. using Apewer;
  2. using Apewer.Internals;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Data;
  6. using System.Runtime.CompilerServices;
  7. namespace Apewer.Source
  8. {
  9. /// <summary>查询数据表。</summary>
  10. public class Query : IQuery, IDisposable
  11. {
  12. private bool _disposed = false;
  13. private bool _success = false;
  14. private string _error = "";
  15. private string _message = "";
  16. private Exception _exception = null;
  17. private List<DataTable> _tables = new List<DataTable>();
  18. #region Property
  19. /// <summary>语句执行成功。</summary>
  20. public bool Success
  21. {
  22. get
  23. {
  24. if (_disposed) return false;
  25. return _success;
  26. }
  27. set
  28. {
  29. if (_disposed) return;
  30. _success = value;
  31. }
  32. }
  33. /// <summary>错误信息。</summary>
  34. public string Error
  35. {
  36. get
  37. {
  38. if (_disposed) return "";
  39. if (!string.IsNullOrEmpty(_error)) return _error;
  40. if (_exception == null) return "";
  41. var error = "";
  42. try { error = _exception.Message; } finally { }
  43. return error;
  44. }
  45. set
  46. {
  47. if (_disposed) return;
  48. _error = value ?? "";
  49. }
  50. }
  51. /// <summary>消息。</summary>
  52. public string Message
  53. {
  54. get
  55. {
  56. if (_disposed) return "";
  57. return _message ?? "";
  58. }
  59. set
  60. {
  61. if (_disposed) return;
  62. _message = value ?? "";
  63. }
  64. }
  65. /// <summary>语句执行失败时的 Exception 对象。</summary>
  66. public Exception Exception
  67. {
  68. get { if (_disposed) return null; return _exception; }
  69. set { if (_disposed) return; _exception = value; }
  70. }
  71. /// <summary>所有结果表。</summary>
  72. public List<DataTable> Tables
  73. {
  74. get { if (_disposed) return new List<DataTable>(); return _tables; }
  75. }
  76. /// <summary>获取默认结果表。如果设置默认结果表,会丢失设置前的所有结果表。</summary>
  77. public DataTable Table
  78. {
  79. get
  80. {
  81. if (_disposed) return null;
  82. if (_tables.Count < 1) return null;
  83. return _tables[0];
  84. }
  85. set
  86. {
  87. if (_disposed) return;
  88. Clear();
  89. if (_disposed) return;
  90. _tables.Add(value);
  91. }
  92. }
  93. /// <summary>所有表中不含内容行。</summary>
  94. public bool Empty
  95. {
  96. get
  97. {
  98. if (_disposed) return true;
  99. if (_tables.Count < 1) return true;
  100. foreach (var table in _tables)
  101. {
  102. if (table == null) continue;
  103. try
  104. {
  105. if (table.Rows.Count > 0) return false;
  106. }
  107. finally { }
  108. }
  109. return true;
  110. }
  111. }
  112. /// <summary>默认表中的数据总行数。</summary>
  113. public int Rows
  114. {
  115. get
  116. {
  117. if (_disposed) return 0;
  118. if (Table != null) return Table.Rows.Count;
  119. else return 0;
  120. }
  121. }
  122. /// <summary>默认表中的数据总列数。</summary>
  123. public int Columns
  124. {
  125. get
  126. {
  127. if (_disposed) return 0;
  128. if (Table != null) return Table.Columns.Count;
  129. else return 0;
  130. }
  131. }
  132. #endregion
  133. #region Text
  134. /// <summary>获取默认表中第 0 行、第 0 列的单元格内容。</summary>
  135. public string Text()
  136. {
  137. if (_disposed) return Constant.EmptyString;
  138. var value = Value();
  139. return Text(value);
  140. }
  141. /// <summary>获取默认表中指定行中第 0 列的内容。</summary>
  142. /// <param name="rowIndex">行索引,从 0 开始。</param>
  143. public string Text(int rowIndex)
  144. {
  145. if (_disposed) return Constant.EmptyString;
  146. var value = Value(rowIndex);
  147. return Text(value);
  148. }
  149. /// <summary>获取默认表中第 0 行指定列的内容。</summary>
  150. /// <param name="columnName">列名称。</param>
  151. public string Text(string columnName)
  152. {
  153. if (_disposed) return Constant.EmptyString;
  154. var value = Value(columnName);
  155. return Text(value);
  156. }
  157. /// <summary>获取默认表中指定单元格的内容。</summary>
  158. /// <param name="rowIndex">行索引,从 0 开始。</param>
  159. /// <param name="columnIndex">列索引,从 0 开始。</param>
  160. public string Text(int rowIndex, int columnIndex)
  161. {
  162. if (_disposed) return Constant.EmptyString;
  163. var value = Value(rowIndex, columnIndex);
  164. return Text(value);
  165. }
  166. /// <summary>获取默认表中指定单元的内容。</summary>
  167. /// <param name="rowIndex">行索引,从 0 开始。</param>
  168. /// <param name="columnName">列名称。</param>
  169. public string Text(int rowIndex, string columnName)
  170. {
  171. if (_disposed) return Constant.EmptyString;
  172. var value = Value(rowIndex, columnName);
  173. return Text(value);
  174. }
  175. /// <summary>搜索默认表。</summary>
  176. /// <param name="conditionColumn">搜索条件:列名。</param>
  177. /// <param name="conditionValue">搜索条件:列值。</param>
  178. /// <param name="resultColumn">搜索结果。</param>
  179. public string Text(string conditionColumn, string conditionValue, string resultColumn)
  180. {
  181. if (_disposed) return Constant.EmptyString;
  182. var value = Value(conditionColumn, conditionValue, resultColumn);
  183. return Text(value);
  184. }
  185. /// <summary>搜索默认表。</summary>
  186. /// <param name="conditionColumn">搜索条件:列名。</param>
  187. /// <param name="conditionValue">搜索条件:列值。</param>
  188. /// <param name="resultColumn">搜索结果。</param>
  189. public string Text(int conditionColumn, string conditionValue, int resultColumn)
  190. {
  191. if (_disposed) return Constant.EmptyString;
  192. var value = Value(conditionColumn, conditionValue, resultColumn);
  193. return Text(value);
  194. }
  195. #endregion
  196. #region Value
  197. /// <summary>获取默认表中第 0 行、第 0 列的单元格内容。</summary>
  198. public object Value()
  199. {
  200. if (_disposed) return null;
  201. return Value(0, 0);
  202. }
  203. /// <summary>获取默认表中指定行中第 0 列的内容。</summary>
  204. /// <param name="rowIndex">行索引,从 0 开始。</param>
  205. public object Value(int rowIndex)
  206. {
  207. if (_disposed) return null;
  208. return Value(rowIndex, 0);
  209. }
  210. /// <summary>获取默认表中第 0 行指定列的内容。</summary>
  211. /// <param name="columnName">列名称。</param>
  212. public object Value(string columnName)
  213. {
  214. if (_disposed) return null;
  215. return Value(0, columnName);
  216. }
  217. /// <summary>获取默认表中指定单元格的内容。</summary>
  218. /// <param name="rowIndex">行索引,从 0 开始。</param>
  219. /// <param name="columnIndex">列索引,从 0 开始。</param>
  220. public object Value(int rowIndex, int columnIndex)
  221. {
  222. if (_disposed) return null;
  223. if (Table != null)
  224. {
  225. if (rowIndex >= 0 && rowIndex < Table.Rows.Count)
  226. {
  227. if (columnIndex >= 0 && columnIndex < Table.Columns.Count)
  228. {
  229. return Table.Rows[rowIndex][columnIndex];
  230. }
  231. }
  232. }
  233. return null;
  234. }
  235. /// <summary>获取默认表中指定单元的内容。</summary>
  236. /// <param name="rowIndex">行索引,从 0 开始。</param>
  237. /// <param name="columnName">列名称。</param>
  238. public object Value(int rowIndex, string columnName)
  239. {
  240. if (_disposed) return null;
  241. if ((Table != null) && !string.IsNullOrEmpty(columnName))
  242. {
  243. if ((rowIndex < Table.Rows.Count) && (rowIndex >= 0))
  244. {
  245. try { return Table.Rows[rowIndex][columnName]; }
  246. catch { }
  247. }
  248. }
  249. return null;
  250. }
  251. /// <summary>搜索默认表。</summary>
  252. /// <param name="conditionColumn">搜索条件:列名。</param>
  253. /// <param name="conditionValue">搜索条件:列值。</param>
  254. /// <param name="resultColumn">搜索结果。</param>
  255. public object Value(string conditionColumn, string conditionValue, string resultColumn)
  256. {
  257. if (_disposed) return null;
  258. if ((Table != null) && (!string.IsNullOrEmpty(conditionColumn)) && (conditionValue != null) && (!string.IsNullOrEmpty(resultColumn)))
  259. {
  260. for (int i = 0; i < Table.Rows.Count; i++)
  261. {
  262. try
  263. {
  264. if (Table.Rows[i][conditionColumn].ToString() == conditionValue) return Table.Rows[i][resultColumn];
  265. }
  266. catch { }
  267. }
  268. }
  269. return null;
  270. }
  271. /// <summary>搜索默认表。</summary>
  272. /// <param name="conditionColumn">搜索条件:列名。</param>
  273. /// <param name="conditionValue">搜索条件:列值。</param>
  274. /// <param name="resultColumn">搜索结果。</param>
  275. public object Value(int conditionColumn, string conditionValue, int resultColumn)
  276. {
  277. if (_disposed) return null;
  278. if ((Table != null) && (conditionColumn >= 0) && (conditionValue != null) && (resultColumn >= 0))
  279. {
  280. if ((conditionColumn < Table.Columns.Count) && (resultColumn < Table.Columns.Count))
  281. {
  282. for (int i = 0; i < Table.Rows.Count; i++)
  283. {
  284. try
  285. {
  286. if (Table.Rows[i][conditionColumn].ToString() == conditionValue) return Table.Rows[i][resultColumn];
  287. }
  288. catch { }
  289. }
  290. }
  291. }
  292. return null;
  293. }
  294. #endregion
  295. #region Method
  296. /// <summary>拆分表组,单独查询。</summary>
  297. public List<Query> Split()
  298. {
  299. var list = new List<Query>();
  300. if (_disposed) return list;
  301. foreach (var table in _tables)
  302. {
  303. if (table == null) continue;
  304. var query = new Query();
  305. query._success = true;
  306. query._tables.Add(table);
  307. list.Add(query);
  308. }
  309. return list;
  310. }
  311. /// <summary>添加数据表。</summary>
  312. public bool Add(DataTable tables)
  313. {
  314. if (_disposed) return false;
  315. if (tables == null) return false;
  316. _tables.Add(tables);
  317. return true;
  318. }
  319. /// <summary>添加数据表。</summary>
  320. public int Add(IEnumerable<DataTable> tables)
  321. {
  322. var count = 0;
  323. if (_disposed) return count;
  324. if (tables == null) return count;
  325. foreach (var table in tables)
  326. {
  327. if (table == null) continue;
  328. _tables.Add(table);
  329. count = count + 1;
  330. }
  331. return count;
  332. }
  333. /// <summary>清除所有表,并释放系统资源。</summary>
  334. public virtual void Clear()
  335. {
  336. if (_tables != null)
  337. {
  338. foreach (var table in _tables)
  339. {
  340. if (table != null)
  341. {
  342. try { table.Dispose(); } catch { }
  343. }
  344. }
  345. _tables.Clear();
  346. }
  347. if (_exception != null) _exception = null;
  348. _success = false;
  349. }
  350. /// <summary>释放系统资源。</summary>
  351. public virtual void Dispose()
  352. {
  353. Clear();
  354. _disposed = true;
  355. // GC.SuppressFinalize(this);
  356. }
  357. /// <summary></summary>
  358. /// <exception cref="Exception"></exception>
  359. public List<T> Fill<T>() where T : Record
  360. {
  361. var list = new List<T>();
  362. var type = typeof(T);
  363. for (int r = 0; r < Rows; r++)
  364. {
  365. list.Capacity = Rows;
  366. var entity = type.Assembly.CreateInstance(type.FullName);
  367. var ts = TableStructure.ParseModel(type);
  368. var properties = type.GetProperties();
  369. foreach (var property in properties)
  370. {
  371. if (ts.Columns.ContainsKey(property.Name) == false) continue;
  372. var setter = property.GetSetMethod();
  373. if (setter == null) continue;
  374. var attribute = ts.Columns[property.Name];
  375. var pt = property.PropertyType;
  376. if (pt.Equals(typeof(object)) || pt.Equals(typeof(Nullable<DateTime>)))
  377. {
  378. setter.Invoke(entity, new object[] { Value(r, attribute.Field) });
  379. }
  380. else if (pt.Equals(typeof(DateTime)))
  381. {
  382. var value = Value(r, attribute.Field);
  383. if (value != null) setter.Invoke(entity, new object[] { Value(r, attribute.Field) });
  384. }
  385. else if (pt.Equals(typeof(byte[])))
  386. {
  387. setter.Invoke(entity, new object[] { (byte[])Value(r, attribute.Field) });
  388. }
  389. else if (pt.Equals(typeof(byte)))
  390. {
  391. setter.Invoke(entity, new object[] { TextConverter.GetByte(Text(r, attribute.Field)) });
  392. }
  393. else if (pt.Equals(typeof(sbyte)))
  394. {
  395. setter.Invoke(entity, new object[] { TextConverter.GetSByte(Text(r, attribute.Field)) });
  396. }
  397. else if (pt.Equals(typeof(short)))
  398. {
  399. setter.Invoke(entity, new object[] { TextConverter.GetInt16(Text(r, attribute.Field)) });
  400. }
  401. else if (pt.Equals(typeof(ushort)))
  402. {
  403. setter.Invoke(entity, new object[] { TextConverter.GetUInt16(Text(r, attribute.Field)) });
  404. }
  405. else if (pt.Equals(typeof(int)))
  406. {
  407. setter.Invoke(entity, new object[] { TextConverter.GetInt32(Text(r, attribute.Field)) });
  408. }
  409. else if (pt.Equals(typeof(uint)))
  410. {
  411. setter.Invoke(entity, new object[] { TextConverter.GetUInt32(Text(r, attribute.Field)) });
  412. }
  413. else if (pt.Equals(typeof(long)))
  414. {
  415. setter.Invoke(entity, new object[] { TextConverter.GetInt64(Text(r, attribute.Field)) });
  416. }
  417. else if (pt.Equals(typeof(ulong)))
  418. {
  419. setter.Invoke(entity, new object[] { TextConverter.GetUInt64(Text(r, attribute.Field)) });
  420. }
  421. else if (pt.Equals(typeof(float)))
  422. {
  423. setter.Invoke(entity, new object[] { TextConverter.GetSingle(Text(r, attribute.Field)) });
  424. }
  425. else if (pt.Equals(typeof(double)))
  426. {
  427. setter.Invoke(entity, new object[] { TextConverter.GetDouble(Text(r, attribute.Field)) });
  428. }
  429. else if (pt.Equals(typeof(decimal)))
  430. {
  431. setter.Invoke(entity, new object[] { TextConverter.GetDecimal(Text(r, attribute.Field)) });
  432. }
  433. else if (pt.Equals(typeof(string)))
  434. {
  435. setter.Invoke(entity, new object[] { Text(r, attribute.Field) });
  436. }
  437. else
  438. {
  439. try
  440. {
  441. setter.Invoke(entity, new object[] { Value(r, attribute.Field) });
  442. }
  443. catch { }
  444. }
  445. }
  446. list.Add((T)entity);
  447. }
  448. return list;
  449. }
  450. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  451. /// <exception cref="ArgumentNullException"></exception>
  452. public List<T> ReadColumn<T>(Func<int, T> filler)
  453. {
  454. var list = new List<T>();
  455. if (filler == null) throw new ArgumentNullException(nameof(filler));
  456. var rows = Rows;
  457. if (rows > 0)
  458. {
  459. list.Capacity = rows;
  460. var added = 0;
  461. for (int r = 0; r < rows; r++)
  462. {
  463. var value = filler(r);
  464. if (value == null) continue;
  465. if (value is string)
  466. {
  467. var valueString = value as string;
  468. if (string.IsNullOrEmpty(valueString)) continue;
  469. }
  470. list.Add(value);
  471. added++;
  472. }
  473. list.Capacity = added;
  474. }
  475. return list;
  476. }
  477. /// <summary>当不指定格式化程序时,自动根据类型选择预置的格式化程序。</summary>
  478. private static Func<object, T> GetValueFormatter<T>()
  479. {
  480. var type = typeof(T);
  481. if (type.Equals(typeof(string))) return TextFormatter<T>;
  482. else return ForceFormatter<T>;
  483. }
  484. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  485. public List<T> ReadColumn<T>(int column = 0, Func<object, T> formatter = null) => ReadColumn((r) => (formatter ?? GetValueFormatter<T>()).Invoke(Value(r, column)));
  486. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  487. /// <exception cref="ArgumentNullException"></exception>
  488. public List<T> ReadColumn<T>(string column, Func<object, T> formatter = null) => ReadColumn((r) => (formatter ?? GetValueFormatter<T>()).Invoke(Value(r, column)));
  489. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  490. public List<string> ReadColumn(int column = 0) => ReadColumn((r) => Text(r, column));
  491. /// <summary>获取指定列的所有值,无效值不加入结果。</summary>
  492. /// <exception cref="ArgumentNullException"></exception>
  493. public List<string> ReadColumn(string column) => ReadColumn((r) => Text(r, column));
  494. #endregion
  495. #region Static
  496. private static string Text(object value)
  497. {
  498. var result = Constant.EmptyString;
  499. if (value != null)
  500. {
  501. if (!value.Equals(DBNull.Value))
  502. {
  503. try
  504. {
  505. result = value.ToString();
  506. }
  507. finally { }
  508. }
  509. }
  510. return result;
  511. }
  512. private static T ForceFormatter<T>(object input) => (T)input;
  513. private static T TextFormatter<T>(object input) => (T)(Text(input) as object);
  514. private static ObjectDisposedException DisposedException { get { return new ObjectDisposedException(typeof(Query).FullName); } }
  515. /// <summary>简单查询:取结果中第 0 列所有单元格的文本形式,可指定查询后关闭服务器连接,返回结果中不包含无效文本。</summary>
  516. public static List<string> SimpleColumn(IDatabase database, string statement, bool close = false)
  517. {
  518. var list = new List<string>();
  519. if (database == null) return list;
  520. if (!database.Connect()) return list;
  521. using (var query = database.Query(statement))
  522. {
  523. var rows = query.Rows;
  524. if (rows > 0)
  525. {
  526. list.Capacity = query.Rows;
  527. var added = 0;
  528. for (int i = 0; i < rows; i++)
  529. {
  530. var cell = TextModifier.Trim(query.Text(i));
  531. if (string.IsNullOrEmpty(cell)) continue;
  532. list.Add(cell);
  533. added++;
  534. }
  535. list.Capacity = added;
  536. }
  537. }
  538. if (close) database.Close();
  539. return list;
  540. }
  541. /// <summary>简单查询:取结果中第 0 行、第 0 列单元格中的文本,可指定查询后关闭服务器连接。</summary>
  542. public static string SimpleCell(IDatabase database, string statement, bool close = false)
  543. {
  544. if (database == null) return "";
  545. if (!database.Connect()) return "";
  546. var vquery = database.Query(statement);
  547. var vcell = TextModifier.Trim(vquery.Text());
  548. vquery.Dispose();
  549. if (close) database.Close();
  550. return vcell;
  551. }
  552. #endregion
  553. #region Extension
  554. /// <summary></summary>
  555. internal static DateTime DateTime(IQuery query, int row, string column)
  556. {
  557. if (query == null) return ClockUtility.Origin;
  558. var value = query.Value(row, column);
  559. if (value == null) return ClockUtility.Origin;
  560. if (value is DateTime) return (DateTime)value;
  561. DateTime result;
  562. var parsed = System.DateTime.TryParse(value.ToString(), out result);
  563. return parsed ? result : ClockUtility.Origin;
  564. }
  565. #endregion
  566. }
  567. }