7 changed files with 1847 additions and 1038 deletions
@ -0,0 +1,360 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Data; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace SunlightCentralizedControlManagement_SCCM_.UserClass |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// 线程安全的 DataTable 管理器
|
||||
|
/// 提供对 DataTable 的安全并发访问
|
||||
|
/// </summary>
|
||||
|
public class DataTableManager : IDisposable |
||||
|
{ |
||||
|
private DataTable _dataTable; |
||||
|
private readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); |
||||
|
private bool _disposed = false; |
||||
|
|
||||
|
#region 构造函数
|
||||
|
public DataTableManager() |
||||
|
{ |
||||
|
_dataTable = new DataTable(); |
||||
|
} |
||||
|
|
||||
|
public DataTableManager(DataTable dataTable) |
||||
|
{ |
||||
|
_dataTable = dataTable ?? throw new ArgumentNullException(nameof(dataTable)); |
||||
|
} |
||||
|
|
||||
|
public DataTableManager(string tableName) |
||||
|
{ |
||||
|
_dataTable = new DataTable(tableName); |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 基本操作
|
||||
|
/// <summary>
|
||||
|
/// 安全地添加列
|
||||
|
/// </summary>
|
||||
|
public void AddColumn(string columnName, Type dataType) |
||||
|
{ |
||||
|
ExecuteWriteOperation(table => |
||||
|
{ |
||||
|
table.Columns.Add(columnName, dataType); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 安全地添加行
|
||||
|
/// </summary>
|
||||
|
public void AddRow(params object[] values) |
||||
|
{ |
||||
|
ExecuteWriteOperation(table => |
||||
|
{ |
||||
|
DataRow newRow = table.NewRow(); |
||||
|
for (int i = 0; i < Math.Min(values.Length, table.Columns.Count); i++) |
||||
|
{ |
||||
|
newRow[i] = values[i] ?? DBNull.Value; |
||||
|
} |
||||
|
table.Rows.Add(newRow); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 安全地更新单元格值
|
||||
|
/// </summary>
|
||||
|
public bool UpdateCell(int rowIndex, string columnName, object value) |
||||
|
{ |
||||
|
return ExecuteWriteOperation(table => |
||||
|
{ |
||||
|
if (IsValidRowIndex(table, rowIndex) && table.Columns.Contains(columnName)) |
||||
|
{ |
||||
|
table.Rows[rowIndex][columnName] = value ?? DBNull.Value; |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 安全地删除行
|
||||
|
/// </summary>
|
||||
|
public bool DeleteRow(int rowIndex) |
||||
|
{ |
||||
|
return ExecuteWriteOperation(table => |
||||
|
{ |
||||
|
if (IsValidRowIndex(table, rowIndex)) |
||||
|
{ |
||||
|
table.Rows[rowIndex].Delete(); |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
}); |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 查询操作
|
||||
|
/// <summary>
|
||||
|
/// 安全地获取行
|
||||
|
/// </summary>
|
||||
|
public DataRow GetRow(int rowIndex) |
||||
|
{ |
||||
|
return ExecuteReadOperation(table => |
||||
|
{ |
||||
|
return IsValidRowIndex(table, rowIndex) ? table.Rows[rowIndex] : null; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 安全地查找行(使用筛选条件)
|
||||
|
/// </summary>
|
||||
|
public DataRow[] FindRows(string filterExpression) |
||||
|
{ |
||||
|
return ExecuteReadOperation(table => |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
return string.IsNullOrEmpty(filterExpression) |
||||
|
? table.Select() |
||||
|
: table.Select(filterExpression); |
||||
|
} |
||||
|
catch (EvaluateException) |
||||
|
{ |
||||
|
return new DataRow[0]; |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 安全地获取行数
|
||||
|
/// </summary>
|
||||
|
public int GetRowCount() |
||||
|
{ |
||||
|
return ExecuteReadOperation(table => table.Rows.Count); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 安全地检查行是否存在
|
||||
|
/// </summary>
|
||||
|
public bool RowExists(int rowIndex) |
||||
|
{ |
||||
|
return ExecuteReadOperation(table => IsValidRowIndex(table, rowIndex)); |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 批量操作
|
||||
|
/// <summary>
|
||||
|
/// 安全地批量添加行
|
||||
|
/// </summary>
|
||||
|
public void BulkAddRows(IEnumerable<object[]> rowsData) |
||||
|
{ |
||||
|
ExecuteWriteOperation(table => |
||||
|
{ |
||||
|
foreach (var rowData in rowsData) |
||||
|
{ |
||||
|
DataRow newRow = table.NewRow(); |
||||
|
for (int i = 0; i < Math.Min(rowData.Length, table.Columns.Count); i++) |
||||
|
{ |
||||
|
newRow[i] = rowData[i] ?? DBNull.Value; |
||||
|
} |
||||
|
table.Rows.Add(newRow); |
||||
|
} |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 安全地清空所有数据
|
||||
|
/// </summary>
|
||||
|
public void Clear() |
||||
|
{ |
||||
|
ExecuteWriteOperation(table => |
||||
|
{ |
||||
|
table.Clear(); |
||||
|
}); |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 数据导出
|
||||
|
/// <summary>
|
||||
|
/// 获取数据快照(线程安全的副本)
|
||||
|
/// </summary>
|
||||
|
public DataTable GetSnapshot() |
||||
|
{ |
||||
|
return ExecuteReadOperation(table => |
||||
|
{ |
||||
|
return table.Copy(); // 创建数据的独立副本
|
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 获取只读视图
|
||||
|
/// </summary>
|
||||
|
public DataView GetReadOnlyView() |
||||
|
{ |
||||
|
return ExecuteReadOperation(table => |
||||
|
{ |
||||
|
return new DataView(table) { AllowEdit = false }; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 导出到新 DataTable(包含结构)
|
||||
|
/// </summary>
|
||||
|
public DataTable ExportToDataTable() |
||||
|
{ |
||||
|
return ExecuteReadOperation(table => |
||||
|
{ |
||||
|
DataTable exported = table.Clone(); |
||||
|
exported.Merge(table, false, MissingSchemaAction.Add); |
||||
|
return exported; |
||||
|
}); |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 锁操作核心
|
||||
|
/// <summary>
|
||||
|
/// 执行读取操作(共享锁)
|
||||
|
/// </summary>
|
||||
|
private T ExecuteReadOperation<T>(Func<DataTable, T> operation) |
||||
|
{ |
||||
|
_lock.EnterReadLock(); |
||||
|
try |
||||
|
{ |
||||
|
return operation(_dataTable); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_lock.ExitReadLock(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 执行写入操作(独占锁)
|
||||
|
/// </summary>
|
||||
|
private void ExecuteWriteOperation(Action<DataTable> operation) |
||||
|
{ |
||||
|
_lock.EnterWriteLock(); |
||||
|
try |
||||
|
{ |
||||
|
operation(_dataTable); |
||||
|
_dataTable.AcceptChanges(); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_lock.ExitWriteLock(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private T ExecuteWriteOperation<T>(Func<DataTable, T> operation) |
||||
|
{ |
||||
|
_lock.EnterWriteLock(); |
||||
|
try |
||||
|
{ |
||||
|
var result = operation(_dataTable); |
||||
|
_dataTable.AcceptChanges(); |
||||
|
return result; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_lock.ExitWriteLock(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private bool IsValidRowIndex(DataTable table, int rowIndex) |
||||
|
{ |
||||
|
return rowIndex >= 0 && rowIndex < table.Rows.Count; |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 高级功能
|
||||
|
/// <summary>
|
||||
|
/// 带超时的安全操作
|
||||
|
/// </summary>
|
||||
|
public bool TryUpdateCell(int rowIndex, string columnName, object value, int timeoutMs = 5000) |
||||
|
{ |
||||
|
if (_lock.TryEnterWriteLock(timeoutMs)) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (IsValidRowIndex(_dataTable, rowIndex) && _dataTable.Columns.Contains(columnName)) |
||||
|
{ |
||||
|
_dataTable.Rows[rowIndex][columnName] = value ?? DBNull.Value; |
||||
|
_dataTable.AcceptChanges(); |
||||
|
return true; |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_lock.ExitWriteLock(); |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// 执行事务性操作
|
||||
|
/// </summary>
|
||||
|
public void ExecuteTransaction(Action<DataTable> transaction) |
||||
|
{ |
||||
|
_lock.EnterWriteLock(); |
||||
|
try |
||||
|
{ |
||||
|
// 开始事务
|
||||
|
_dataTable.BeginLoadData(); |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
transaction(_dataTable); |
||||
|
_dataTable.AcceptChanges(); |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
_dataTable.RejectChanges(); |
||||
|
throw; |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_dataTable.EndLoadData(); |
||||
|
} |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
_lock.ExitWriteLock(); |
||||
|
} |
||||
|
} |
||||
|
#endregion
|
||||
|
|
||||
|
#region 属性和清理
|
||||
|
public string TableName |
||||
|
{ |
||||
|
get => ExecuteReadOperation(table => table.TableName); |
||||
|
set => ExecuteWriteOperation(table => table.TableName = value); |
||||
|
} |
||||
|
|
||||
|
public DataColumnCollection Columns |
||||
|
{ |
||||
|
get => ExecuteReadOperation(table => table.Columns); |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
if (!_disposed) |
||||
|
{ |
||||
|
_lock?.Dispose(); |
||||
|
_dataTable?.Dispose(); |
||||
|
_disposed = true; |
||||
|
} |
||||
|
GC.SuppressFinalize(this); |
||||
|
} |
||||
|
|
||||
|
~DataTableManager() |
||||
|
{ |
||||
|
Dispose(); |
||||
|
} |
||||
|
#endregion
|
||||
|
} |
||||
|
} |
File diff suppressed because it is too large
Loading…
Reference in new issue