S8MonitoringRowSet.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. using System.Data;
  2. namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess;
  3. /// <summary>
  4. /// S8 监控数据的 canonical 结果集。
  5. ///
  6. /// 承担原先 <see cref="DataTable"/> 的两个职责:承载行、回答"结果集是否含某列"。
  7. /// 后者是 evaluator canonical→params 回退逻辑的输入,语义必须与 DataTable.Columns.Contains 一致
  8. /// (列集合在整个结果集内稳定,因此在结果集层面回答,而不是逐行判断)。
  9. /// </summary>
  10. public sealed class S8MonitoringRowSet
  11. {
  12. private readonly HashSet<string> _columns;
  13. private S8MonitoringRowSet(IReadOnlyList<S8MonitoringRow> rows, HashSet<string> columns)
  14. {
  15. Rows = rows;
  16. _columns = columns;
  17. }
  18. /// <summary>结果集行。</summary>
  19. public IReadOnlyList<S8MonitoringRow> Rows { get; }
  20. /// <summary>结果集列名(去重,OrdinalIgnoreCase)。</summary>
  21. public IReadOnlyCollection<string> Columns => _columns;
  22. /// <summary>结果集是否包含该列。驱动 evaluator 的 canonical 优先 / params 回退分支。</summary>
  23. public bool HasColumn(string? columnName) =>
  24. !string.IsNullOrWhiteSpace(columnName) && _columns.Contains(columnName!);
  25. /// <summary>空结果集。</summary>
  26. public static S8MonitoringRowSet Empty { get; } =
  27. new(Array.Empty<S8MonitoringRow>(), new HashSet<string>(StringComparer.OrdinalIgnoreCase));
  28. /// <summary>由 Legacy SQL / API 取数结果构造。保留全部列,供 payload 落盘与 params 回退使用。</summary>
  29. public static S8MonitoringRowSet FromDataTable(DataTable table)
  30. {
  31. var columns = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
  32. foreach (DataColumn column in table.Columns)
  33. columns.Add(column.ColumnName);
  34. var rows = new List<S8MonitoringRow>(table.Rows.Count);
  35. foreach (DataRow row in table.Rows)
  36. rows.Add(S8MonitoringRow.FromDataRow(row));
  37. return new S8MonitoringRowSet(rows, columns);
  38. }
  39. /// <summary>
  40. /// 由标准 Provider 产出的 canonical 行构造。列集合取所有行键的并集
  41. /// (标准 Provider 各行结构一致,取并集可容忍可选列在部分行缺失)。
  42. /// </summary>
  43. public static S8MonitoringRowSet FromRows(IEnumerable<S8MonitoringRow> rows)
  44. {
  45. var list = rows as IReadOnlyList<S8MonitoringRow> ?? rows.ToList();
  46. var columns = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
  47. foreach (var row in list)
  48. foreach (var key in row.Values.Keys)
  49. columns.Add(key);
  50. return new S8MonitoringRowSet(list, columns);
  51. }
  52. }