using System.Data; namespace Admin.NET.Plugin.AiDOP.Service.S8.Rules.DataAccess; /// /// S8 监控数据的 canonical 结果集。 /// /// 承担原先 的两个职责:承载行、回答"结果集是否含某列"。 /// 后者是 evaluator canonical→params 回退逻辑的输入,语义必须与 DataTable.Columns.Contains 一致 /// (列集合在整个结果集内稳定,因此在结果集层面回答,而不是逐行判断)。 /// public sealed class S8MonitoringRowSet { private readonly HashSet _columns; private S8MonitoringRowSet(IReadOnlyList rows, HashSet columns) { Rows = rows; _columns = columns; } /// 结果集行。 public IReadOnlyList Rows { get; } /// 结果集列名(去重,OrdinalIgnoreCase)。 public IReadOnlyCollection Columns => _columns; /// 结果集是否包含该列。驱动 evaluator 的 canonical 优先 / params 回退分支。 public bool HasColumn(string? columnName) => !string.IsNullOrWhiteSpace(columnName) && _columns.Contains(columnName!); /// 空结果集。 public static S8MonitoringRowSet Empty { get; } = new(Array.Empty(), new HashSet(StringComparer.OrdinalIgnoreCase)); /// 由 Legacy SQL / API 取数结果构造。保留全部列,供 payload 落盘与 params 回退使用。 public static S8MonitoringRowSet FromDataTable(DataTable table) { var columns = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (DataColumn column in table.Columns) columns.Add(column.ColumnName); var rows = new List(table.Rows.Count); foreach (DataRow row in table.Rows) rows.Add(S8MonitoringRow.FromDataRow(row)); return new S8MonitoringRowSet(rows, columns); } /// /// 由标准 Provider 产出的 canonical 行构造。列集合取所有行键的并集 /// (标准 Provider 各行结构一致,取并集可容忍可选列在部分行缺失)。 /// public static S8MonitoringRowSet FromRows(IEnumerable rows) { var list = rows as IReadOnlyList ?? rows.ToList(); var columns = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (var row in list) foreach (var key in row.Values.Keys) columns.Add(key); return new S8MonitoringRowSet(list, columns); } }