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