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.

197 lines
6.8 KiB

using Apewer.Internals;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Data;
using static Apewer.TextUtility;
namespace Apewer.Source
{
/// <summary>System.Data.DataTable 装箱查询。</summary>
public sealed class Query : IQuery, IDisposable, IToJson
{
private bool _disposed = false;
private bool _success = false;
private string _message = null;
private DataTable _table = null;
private DataTable[] _tables = null;
/// <summary>创建实例,默认状态为失败。</summary>
public Query(bool success = false, string message = null)
{
_success = false;
_message = message;
}
/// <summary>创建实例,Exception 为 NULL 时成功,非 NULL 时失败。</summary>
public Query(Exception exception)
{
_success = exception == null;
_message = RuntimeUtility.Message(exception);
}
/// <summary>创建实例,包装一个 DataTable 对象,数据表为 NULL 时失败,非 NULL 时成功。</summary>
public Query(DataTable table)
{
_table = table;
_success = table != null;
_message = table == null ? "未获取有效的数据表。" : null;
}
/// <summary>创建实例,包装一个 DataTable 对象。</summary>
public Query(DataTable table, bool success, string message = null)
{
_table = table;
_success = success;
_message = message;
}
/// <summary>创建实例,包装多个 DataTable 对象。</summary>
public Query(DataTable[] tables, bool success = true, string message = null)
{
_tables = tables;
_success = success;
_message = message;
if (tables != null && tables.Length > 0) _table = tables[0];
}
/// <summary>从 <see cref="Query"/> 到 <see cref="Boolean"/> 的隐式转换,判断 <see cref="Query"/> 执行成功且包含表。</summary>
public static implicit operator bool(Query query) => query != null && query.Success && query.Table != null;
/// <summary>从 <see cref="DataTable"/> 到 <see cref="Query"/> 的隐式转换。</summary>
public static implicit operator Query(DataTable table) => new Query(table, table != null, null);
/// <summary>从 <see cref="Query"/> 到 <see cref="DataTable"/> 的隐式转换。</summary>
public static implicit operator DataTable(Query query) => query?.Table;
#region Property
/// <summary>语句执行成功。</summary>
public bool Success { get => _success; }
/// <summary>消息。</summary>
public string Message { get => _message; }
/// <summary>所有结果表。</summary>
public DataTable[] Tables { get => _tables; }
/// <summary>获取默认结果表。如果设置默认结果表,会丢失设置前的所有结果表。</summary>
public DataTable Table { get => _table; }
/// <summary>默认表中的数据总行数。</summary>
public int Rows { get => _table == null ? 0 : _table.Rows.Count; }
/// <summary>默认表中的数据总列数。</summary>
public int Columns { get => _table == null ? 0 : _table.Columns.Count; }
#endregion
#region Value
/// <summary>获取默认表中指定单元格的内容。</summary>
/// <param name="rowIndex">行索引,从 0 开始。</param>
/// <param name="columnIndex">列索引,从 0 开始。</param>
public object Value(int rowIndex, int columnIndex) => Table.Value(rowIndex, columnIndex);
/// <summary>获取默认表中指定单元的内容。</summary>
/// <param name="rowIndex">行索引,从 0 开始。</param>
/// <param name="columnName">列名称/字段名称,此名称不区分大小写。</param>
public object Value(int rowIndex, string columnName) => Table.Value(rowIndex, columnName);
#endregion
#region Method
/// <summary>释放系统资源。</summary>
public void Dispose()
{
if (_disposed) return;
if (_tables != null)
{
foreach (var table in _tables) RuntimeUtility.Dispose(table);
_tables = null;
}
RuntimeUtility.Dispose(_table);
_table = null;
_tables = null;
_disposed = true;
// GC.SuppressFinalize(this);
}
#endregion
#region 模型化、IToJson
/// <summary>转换为 Json 对象。</summary>
public Json ToJson()
{
var jsonObject = Json.NewObject();
jsonObject.SetProperty("success", _success);
jsonObject.SetProperty("message", _message);
if (Table != null)
{
var columns = SourceUtility.ToJson(Table.Columns);
jsonObject.SetProperty("columns", columns);
var rows = SourceUtility.ToJson(Table.Rows);
jsonObject.SetProperty("rows", rows);
}
return jsonObject;
}
/// <summary>转换为模型数组。</summary>
public ObjectSet[] ToArray()
{
var oss = null as ObjectSet[];
var table = _table;
if (!_disposed && table != null)
{
var width = table.Columns.Count;
var names = new string[width];
for (var c = 0; c < width; c++)
{
var name = table.Columns[c].ColumnName;
if (name.IsEmpty()) continue;
if (names.Contains(name)) continue;
names[c] = name;
}
var unnamed = 1;
for (var c = 0; c < width; c++)
{
if (names[c] != null) continue;
while (true)
{
var name = "unnamed_" + unnamed.ToString();
unnamed++;
if (names.Contains(name)) continue;
names[c] = name;
break;
}
}
var height = table.Rows.Count;
oss = new ObjectSet[height];
for (var r = 0; r < height; r++)
{
var os = new ObjectSet();
var dict = os.Origin;
for (var c = 0; c < width; c++)
{
var v = Value(r, c);
dict.Add(names[c], v.IsNull() ? null : v);
}
oss[r] = os;
}
}
return oss;
}
#endregion
}
}