Actually we have created a single form .NET windows application which fetches data from Dy namics CRM table and creates and writes the data to an access DB file.
The application works fine for few systems but for others it crashes randomly
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 is not the only faulting module, few Other crash event logs mentioned the faulting module name as: ucrtbase.dll, ACEOLEDB.DLL, System.Data.ni.dll
After analysing the crash dump file I beleive the issue could be for the below Insert method for accesdb but couldn't find how further debug and fix it.
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}");
}
}
The issue was that the oleDbCommand
instance was not getting disposed properly. We were disposing oleDbConnection
instances but not oleDbCommand
one. Without this memory were not getting disposed properly and the app was crashing with random module errors.
The fix was to move that portion of code into using block.
This is the update code which worked.
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}");
}
}