实际上我们已经创建了一个单一表单的 .NET Windows 应用程序,它从 Dy 获取数据 namics CRM 表并创建数据并将其写入访问数据库文件。
该应用程序在少数系统上运行良好,但对于其他系统来说它会随机崩溃
Faulting application name: XXXXDatabase.exe, version: 4.9.0.0, time stamp: 0x67489d47
Faulting module name: clr.dll, version: 4.8.9290.0, time stamp: 0x67214bca
Exception code: 0xc0000005
Fault offset: 0x000000000006cb43
Faulting process id: 0x251c
Faulting application start time: 0x01db67227f8c0e44
Faulting application path: C:\Program Files\Monterey Insight\Product Database Generator\XXXXDatabase.exe
Faulting module path: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Report Id: a797901f-709f-4f6a-bf62-762d93ccf0b6
Faulting package full name:
Faulting package-relative application ID:
Clr.dll 不是唯一的故障模块,很少有其他崩溃事件日志提到故障模块名称为:ucrtbase.dll、ACEOLEDB.DLL、System.Data.ni.dll
分析故障转储文件后,我相信问题可能出在以下 accesdb 的插入方法上,但找不到如何进一步调试和修复它。
public int Insert(string tableName, object dbObject)
{
var query = string.Empty;
try
{
if (dbObject == null)
{
return 0;
}
//
var columns = ((BaseAccessModel)dbObject).GetColumns();
StringBuilder columnsQuery = new StringBuilder("");
StringBuilder parametersQuery = new StringBuilder("");
OleDbCommand cmd = new OleDbCommand();
object value = null;
for (int i = 0; i < columns.Count; i++)
{
value = GetColumnValue(columns[i], dbObject);
if (value != null)
{
columnsQuery.Append("[" + columns[i].ColumnName + "],");
parametersQuery.Append("[@" + columns[i].ColumnName + "],");
cmd.Parameters.Add(columns[i].ColumnName, columns[i].DBColumnType).Value = GetColumnValue(columns[i], dbObject);
}
}
//
query = string.Format("INSERT INTO [{0}] ({1}) VALUES ({2});", tableName, columnsQuery.ToString().Trim(','), parametersQuery.ToString().Trim(','));
cmd.CommandText = query;
cmd.Connection = _conn;
return cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
throw new Exception($"Failed to insert: {query} - Message: {ex.Message}");
}
}
问题在于
oleDbCommand
实例未得到正确处置。我们正在处理 oleDbConnection
实例,但没有处理 oleDbCommand
实例。如果没有这个内存,就无法正确处理,应用程序就会因随机模块错误而崩溃。
修复方法是将这部分代码移至 using 块中。
这是有效的更新代码。
public int Insert(string tableName, object dbObject)
{
var query = string.Empty;
try
{
if (dbObject == null)
{
return 0;
}
//
var columns = ((BaseAccessModel)dbObject).GetColumns();
StringBuilder columnsQuery = new StringBuilder("");
StringBuilder parametersQuery = new StringBuilder("");
using (OleDbCommand cmd = new OleDbCommand())
{
object value = null;
for (int i = 0; i < columns.Count; i++)
{
value = GetColumnValue(columns[i], dbObject);
if (value != null)
{
columnsQuery.Append("[" + columns[i].ColumnName + "],");
parametersQuery.Append("[@" + columns[i].ColumnName + "],");
cmd.Parameters.Add(columns[i].ColumnName, columns[i].DBColumnType).Value = GetColumnValue(columns[i], dbObject);
}
}
//
query = string.Format("INSERT INTO [{0}] ({1}) VALUES ({2});", tableName, columnsQuery.ToString().Trim(','), parametersQuery.ToString().Trim(','));
cmd.CommandText = query;
cmd.Connection = _conn;
return cmd.ExecuteNonQuery();
}
}
catch (Exception ex)
{
throw new Exception($"Failed to insert: {query} - Message: {ex.Message}");
}
}