MySqlConnector icon indicating copy to clipboard operation
MySqlConnector copied to clipboard

System.InvalidProgramException: Common Language Runtime detected an invalid program.

Open shajiltetherfi opened this issue 1 year ago • 7 comments
trafficstars

Software versions MySqlConnector version: 2.3.6 Server type (MySQL, MariaDB, Aurora, etc.) and version: MYSQL .NET version: >.NET6 (Optional) ORM NuGet packages and versions:

Describe the bug System.InvalidProgramException: Common Language Runtime detected an invalid program. Exception Full exception message and call stack (if applicable)

2024-10-17 13:54:41,154 [39] INFO Core.ORM.MySqlAdapter - Connection Opened:
2024-10-17 13:54:41,155 [39] INFO Core.ORM.MySqlAdapter - Start Connection Execute with: CREATE TEMPORARY TABLE TmpIn_CMM_Role_Pages_6541bc52679842279c38e65b978d250b SELECT RoleID , PageName , USER_ACCESS , ADD_ACCESS , EDIT_ACCESS , DELETE_ACCESS , EXPORT_ACCESS , LAST_CHANGED_BY , LAST_CHANGED_ON  FROM CMM_Role_Pages target LIMIT 0;:
2024-10-17 13:54:41,160 [39] ERROR Core.ORM.MySqlAdapter - Catch 2: System.InvalidProgramException: Common Language Runtime detected an invalid program.
   at MySqlConnector.MySqlCommand.ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
   at MySqlConnector.MySqlCommand.ExecuteNonQuery() in /_/src/MySqlConnector/MySqlCommand.cs:line 108
   at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, CommandDefinition& command, Action`2 paramReader) in C:\projects\dapper\Dapper\SqlMapper.cs:line 2827
   at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition& command) in C:\projects\dapper\Dapper\SqlMapper.cs:line 570
   at Core.ORM.MySqlAdapter.BulkUpsert[T](IDbConnection connection, IDbTransaction transaction, IEnumerable`1 data, String tableName, Type type, Int32 bulkCopyTimeout, Nullable`1 commandTimeout):
2024-10-17 13:54:41,161 [39] ERROR OCM.Utilities.SqlDataAccess - ExecuteBulkUpsertQuery:System.InvalidProgramException: Common Language Runtime detected an invalid program.
   at MySqlConnector.MySqlCommand.ExecuteNonQueryAsync(IOBehavior ioBehavior, CancellationToken cancellationToken)
   at MySqlConnector.MySqlCommand.ExecuteNonQuery() in /_/src/MySqlConnector/MySqlCommand.cs:line 108
   at Dapper.SqlMapper.ExecuteCommand(IDbConnection cnn, CommandDefinition& command, Action`2 paramReader) in C:\projects\dapper\Dapper\SqlMapper.cs:line 2827
   at Dapper.SqlMapper.ExecuteImpl(IDbConnection cnn, CommandDefinition& command) in C:\projects\dapper\Dapper\SqlMapper.cs:line 570
   at Core.ORM.MySqlAdapter.BulkUpsert[T](IDbConnection connection, IDbTransaction transaction, IEnumerable`1 data, String tableName, Type type, Int32 bulkCopyTimeout, Nullable`1 commandTimeout)
   at Core.ORM.DapperExtensions.BulkUpsert[T](IDbConnection connection, IEnumerable`1 data, IDbTransaction transaction, Int32 batchSize, Int32 bulkCopyTimeout, Nullable`1 commandTimeout)
   at OCM.Utilities.SqlDataAccess.ExecuteBulkUpsertQuery[T](IEnumerable`1 obj)

Code sample

public void BulkUpsert<T>(IDbConnection connection, IDbTransaction transaction, IEnumerable<T> data, string tableName, Type type, int bulkCopyTimeout, int? commandTimeout)
{
    var allProperties = PropertiesCache.TypePropertiesCache(type);
    var keyProperties = PropertiesCache.KeyPropertiesCache(type);
    var computedProperties = PropertiesCache.ComputedPropertiesCache(type);
    var columns = PropertiesCache.GetColumnNamesCache(type);
 
    var allPropertiesExceptComputed = allProperties.Except(computedProperties).ToList();
    //var tempToBeInserted = $"TempInsert_{tableName}_{Guid.NewGuid().ToString("N")}".Replace(".", string.Empty);
    var tempToBeInserted = $"TmpIn_{tableName}_{Guid.NewGuid().ToString("N")}".Replace(".", string.Empty);
    tempToBeInserted = tempToBeInserted.Substring(0, Math.Min(tempToBeInserted.Length, 64));
 
    var allPropertiesExceptKeyAndComputed = allProperties.Except(keyProperties.Union(computedProperties)).ToList();
    var mergingProperties = PropertiesCache.MergeConditionPropertiesCache(type);
 
    string tempSql = $@"CREATE TEMPORARY TABLE  {tempToBeInserted} SELECT { GetColumnsStringSqlServer(allPropertiesExceptComputed, columns)} FROM {tableName} target LIMIT 0;";
 
 
    var con = new MySqlConnection(connection.ConnectionString);
 
    if (!con.ConnectionString.ToLower().Replace(" ", "").Contains("allowloadlocalinfile=true"))
    {
        con.ConnectionString += ";allowloadlocalinfile = true;";
    }
 
    var bulkCopy = new MySqlBulkCopy(con, transaction as MySqlTransaction);
 
    try
    {
        con.Open();
        con.Execute(tempSql, null, transaction as MySqlTransaction, commandTimeout);
        List<MySqlBulkCopyColumnMapping> colMappings = new List<MySqlBulkCopyColumnMapping>();
        int i = 0;
        foreach (var property in allPropertiesExceptComputed)
        {
            colMappings.Add(new MySqlBulkCopyColumnMapping(i, property.Name));
            i++;
        }
 
        bulkCopy.BulkCopyTimeout = bulkCopyTimeout;
        //bulkCopy.BatchSize = batchSize;
        bulkCopy.DestinationTableName = tempToBeInserted;
        var dataReader = ToDataTable(data, allPropertiesExceptComputed).CreateDataReader();
        bulkCopy.WriteToServer(dataReader);
 
        string mergeCondition = string.Join(" AND ", mergingProperties.Select(c => $"{columns[c.Name]}={columns[c.Name]} "));
 
        string executeStatement = $@"
                    REPLACE INTO {tableName} ({GetColumnsStringSqlServer(allPropertiesExceptKeyAndComputed, columns)})
                    SELECT {GetColumnsStringSqlServer(allPropertiesExceptKeyAndComputed, columns)} FROM {tempToBeInserted}
                    WHERE ({mergeCondition});
 
                    DROP TABLE {tempToBeInserted};";
 
        con.Execute(executeStatement, null, transaction as MySqlTransaction, commandTimeout);
    }
    catch (MySqlException ex)
    {
        if (ex.Message.Contains("Received an invalid column length from the bcp client for colid"))
        {
            string pattern = @"\d+";
            Match match = Regex.Match(ex.Message.ToString(), pattern);
            var index = Convert.ToInt32(match.Value) - 1;
 
            FieldInfo fi = typeof(MySqlBulkCopy).GetField("_sortedColumnMappings", BindingFlags.NonPublic | BindingFlags.Instance);
            var sortedColumns = fi.GetValue(bulkCopy);
            var items = (Object[])sortedColumns.GetType().GetField("_items", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(sortedColumns);
 
            FieldInfo itemdata = items[index].GetType().GetField("_metadata", BindingFlags.NonPublic | BindingFlags.Instance);
            var metadata = itemdata.GetValue(items[index]);
 
            var column = metadata.GetType().GetField("column", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata);
            var length = metadata.GetType().GetField("length", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).GetValue(metadata);
            throw new Exception(String.Format("Column: {0} contains data with a length greater than: {1}", column, length));
        }
 
        throw ex;
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

Expected behavior A clear and concise description of what you expected to happen.

Additional context image

shajiltetherfi avatar Oct 18 '24 14:10 shajiltetherfi