MES-ETL/MesETL.App/DataRecord.cs

183 lines
6.0 KiB
C#
Raw Permalink Normal View History

namespace MesETL.App;
2024-01-12 16:50:37 +08:00
2024-01-29 09:29:16 +08:00
public class DataRecord : ICloneable
2023-12-28 15:18:03 +08:00
{
2024-01-29 09:29:16 +08:00
private static int IndexOfIgnoreCase(IList<string> list, string value)
{
var idx = -1;
for (var i = 0; i < list.Count; i++)
{
if (list[i].Equals(value, StringComparison.OrdinalIgnoreCase))
2024-01-29 09:29:16 +08:00
{
idx = i;
break;
}
}
return idx;
}
2023-12-28 15:18:03 +08:00
private readonly List<string> _fields;
private readonly List<string> _headers;
2024-12-10 14:03:09 +08:00
/// <summary>
/// 字段列表
/// </summary>
public IReadOnlyList<string> Fields => _fields;
2024-12-10 14:03:09 +08:00
/// <summary>
/// 表头列表
/// </summary>
public IReadOnlyList<string> Headers => _headers;
2024-12-10 14:03:09 +08:00
/// <summary>
/// 来源表名
/// </summary>
2023-12-28 15:18:03 +08:00
public string TableName { get; }
2024-12-10 14:03:09 +08:00
/// <summary>
/// 需要输出的数据库
/// </summary>
2024-01-29 09:29:16 +08:00
public string? Database { get; set; }
2024-12-10 14:03:09 +08:00
/// <summary>
/// 所有字段的总字符数量
/// </summary>
2024-02-09 19:08:57 +08:00
public long FieldCharCount { get; }
2024-12-10 14:03:09 +08:00
/// <summary>
/// 忽略这个记录,不会被输出
/// </summary>
public bool Ignore { get; set; }
2023-12-29 16:16:05 +08:00
2023-12-28 15:18:03 +08:00
public DataRecord(IEnumerable<string> fields, string tableName, IEnumerable<string> headers,
string? database = null)
2023-12-28 15:18:03 +08:00
{
_fields = fields.ToList();
2024-01-29 09:29:16 +08:00
TableName = tableName;
_headers = headers.ToList();
2024-01-29 09:29:16 +08:00
Database = database;
if (_fields.Count != _headers.Count)
2023-12-28 15:18:03 +08:00
throw new ArgumentException(
$"The number of fields does not match the number of headers. Expected: {_headers.Count} Got: {_fields.Count} Fields: {string.Join(',', _fields)}",
2023-12-28 15:18:03 +08:00
nameof(fields));
FieldCharCount = _fields.Sum(x => (long)x.Length);
2023-12-28 15:18:03 +08:00
}
2024-12-10 14:03:09 +08:00
/// <summary>
/// 使用索引访问字段
/// </summary>
/// <param name="index"></param>
2023-12-29 16:16:05 +08:00
public string this[int index]
{
get => _fields[index];
set => _fields[index] = value;
2023-12-29 16:16:05 +08:00
}
2023-12-28 15:18:03 +08:00
2024-12-10 14:03:09 +08:00
/// <summary>
/// 使用列名访问字段,不区分大小写
/// </summary>
/// <param name="columnName"></param>
public string this[string columnName]
{
get => GetField(columnName);
set => SetField(columnName, value);
}
2023-12-28 15:18:03 +08:00
2024-12-10 14:03:09 +08:00
/// <summary>
/// 尝试获取某个字段值
2024-12-10 14:03:09 +08:00
/// </summary>
/// <param name="columnName"></param>
/// <param name="value"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public bool TryGetField(string columnName, out string value)
{
value = string.Empty;
if (_headers is null)
throw new InvalidOperationException("Cannot get field when headers of a record have not been set.");
var idx = IndexOfIgnoreCase(_headers, columnName);
if (idx == -1)
return false;
value = _fields[idx];
return true;
}
2024-01-16 18:00:23 +08:00
2024-12-10 14:03:09 +08:00
/// <summary>
/// 获取一条记录的某个字段值
/// TODO: 最好能优化至O(1)
2024-12-10 14:03:09 +08:00
/// </summary>
/// <param name="columnName"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
/// <exception cref="IndexOutOfRangeException"></exception>
public string GetField(string columnName)
{
if (_headers is null)
throw new InvalidOperationException("记录的表头尚未设置,无法赋值");
var idx = IndexOfIgnoreCase(_headers, columnName);
if (idx is -1)
throw new IndexOutOfRangeException(
$"列 '{columnName}' 不存在于该纪录中,表名 '{TableName}");
return _fields[idx];
}
2024-01-18 14:36:36 +08:00
2024-12-10 14:03:09 +08:00
/// <summary>
/// 为记录的一个字段赋值,如果该字段名不存在则会抛出异常
2024-12-10 14:03:09 +08:00
/// </summary>
/// <param name="columnName">列名</param>
/// <param name="value">值</param>
2024-12-10 14:03:09 +08:00
/// <returns></returns>
/// <exception cref="InvalidOperationException">该记录的表头尚未初始化,你可能在错误的阶段调用了该方法</exception>
/// <exception cref="IndexOutOfRangeException">输入的字段名不存在于该记录中</exception>
public void SetField(string columnName, string value)
2024-01-16 18:00:23 +08:00
{
2024-12-10 14:03:09 +08:00
// 表头检查
if (_headers is null)
2024-12-10 14:03:09 +08:00
throw new InvalidOperationException("记录的表头尚未设置,无法赋值");
var idx = IndexOfIgnoreCase(_headers, columnName);
2024-01-16 18:00:23 +08:00
if (idx is -1)
2024-01-29 09:29:16 +08:00
throw new IndexOutOfRangeException(
$"列 '{columnName}' 不存在于该纪录中,表名 '{TableName}");
_fields[idx] = value;
}
/// <summary>
/// 在记录中追加一个字段
/// </summary>
/// <param name="columnName">字段名</param>
/// <param name="value">字段值</param>
/// <exception cref="InvalidOperationException">记录的表头尚未初始化,你可能在错误的阶段调用了此方法</exception>
/// <exception cref="ArgumentException">提供的字段名已存在于该记录中</exception>
public void AppendField(string columnName, string value)
{
if (_headers is null)
throw new InvalidOperationException("记录的表头尚未设置,无法赋值");
var idx = IndexOfIgnoreCase(_headers, columnName);
if (idx is > 0)
throw new ArgumentException($"字段名 '{columnName}' 已存在于该记录中,无法重复添加", nameof(columnName));
_headers.Add(columnName);
_fields.Add(value);
2024-01-16 18:00:23 +08:00
}
2024-01-29 09:29:16 +08:00
public void RemoveField(string columnName)
{
var idx = IndexOfIgnoreCase(_headers, columnName);
2024-01-29 09:29:16 +08:00
if (idx == -1)
throw new InvalidOperationException($"{TableName}: 列名 '{columnName}' 不存在");
_fields.RemoveAt(idx);
_headers.Remove(columnName);
2024-01-29 09:29:16 +08:00
}
2024-01-18 14:36:36 +08:00
public bool HeaderExists(string columnName) => IndexOfIgnoreCase(_headers, columnName) != -1;
2024-01-29 09:29:16 +08:00
public object Clone()
{
return new DataRecord(new List<string>(_fields), TableName, new List<string>(_headers), Database);
2024-01-18 14:36:36 +08:00
}
2023-12-28 15:18:03 +08:00
}