Null value in Statements.Find

Hello,

We have a legacy .NET Framework application. Everything works fine until version 10.0.0.1599. Starting version 10.0.0.1605 we have an error in the override of ProcessDelta (it’s very old code…). The error happens in the CustomCreateParameterMappings function on the line:
daStatement = aDataTableSchema.Statements.Find(delegate (SchemaSQLStatement e) { return e.Name.Equals(aConnection.Name); });

The line returns null without an error. Until version 1599 this returned the correct SchemaSqlStatement.

We hope you can help is. We want to migrate to Visual Studio 2026, but can’t because we cannot find why this Find method returns null.

You can find the override code with the extra functions beneath.

Thanks you in advance.

protected override void ProcessDelta(Delta aDelta, bool aProcessDeletes, bool aProcessInserts, bool aProcessUpdates, RemObjects.Common.Collections.NamedObjectCollection aDetailDeltas)
{
  BusinessProcessor bizProcessor = null;
  if (!BusinessProcessors.TryGetValue(aDelta.Name, out bizProcessor))
  {
    bizProcessor = new BusinessProcessor();         // Inject custom businessprocessor
    bizProcessor.ReferencedDataTable = aDelta.Name;

     // Ommits calling AfterAutoCreateBusinessProcessor event

     RegisterBusinessProcessor(bizProcessor);

     bizProcessor.ProcessDelta(Connection, ServiceSchema, aDelta, aProcessDeletes, aProcessInserts, aProcessUpdates);
   }
   else
   {
     DeltaProcessor deltaProcessor = null;
     try
     {
         // We only use these businessprocessors to wrap them, and to extract their property-information
         // to find the prefered update-commands
         // TODO: watch for a better way to associate these commands. (The Scheme seems to be an appropriate place)
         deltaProcessor = new DeltaProcessor(bizProcessor);
         deltaProcessor.CustomProcessDelta(Connection, ServiceSchema, aDelta, aProcessDeletes, aProcessInserts, aProcessUpdates);
     }
     finally
     {
         if (deltaProcessor != null) deltaProcessor.Dispose();
     }
 }
 SynchronizeDetail(aDelta, aDetailDeltas);
}

public void CustomProcessDelta(IAbstractConnection aCon, ServiceSchema aServiceSchema, Delta aDelta,
    bool aProcessDeletes, bool aProcessInserts, bool aProcessUpdates)
{
    //IgnoreStaticCommands = false;

    try
    {
        //this.ProcessDelta(aCon, aSchema, aDelta, aProcessDeletes, aProcessInserts, aProcessUpdates);
        string valName = "";
        string parNameSymbol = aCon.DataProviderInfo.ParameterNameSymbol;
        int errorCode = 0;

        IDbCommand cmdDelete = null;
        IDbCommand cmdInsert = null;
        IDbCommand cmdUpdate = null;

        IDbCommand curCommand = null;

        List<ParameterDirection> outputArray = new List<ParameterDirection>(2);
        outputArray.Add(System.Data.ParameterDirection.InputOutput);
        outputArray.Add(System.Data.ParameterDirection.Output);

        ParamMappingCollection mapDelete = null;
        ParamMappingCollection mapInsert = null;
        ParamMappingCollection mapUpdate = null;

        ParamMappingCollection curMap = null;

        SchemaParameterCollection pars = new SchemaParameterCollection();

        SchemaSQLStatement statement = null;
        SchemaColumnMapping mapping = null;

        SchemaDataTable dataTableSchema =
            aServiceSchema.DataTables[aDelta.Name];

        if (aProcessDeletes)
        {
            if ((DeleteCommandName.Length > 0))// && (!IgnoreStaticCommands))
            {
                cmdDelete = aServiceSchema.NewCommand(aCon, DeleteCommandName);
                pars = aServiceSchema.Commands[DeleteCommandName].Parameters;
            }
            else
            {
                cmdDelete = CreateUpdateCommand(aCon, dataTableSchema, RemObjects.DataAbstract.ChangeType.Delete, null, UpdateMode, null, out pars);
            }

            mapDelete = CustomCreateParameterMappings(aCon, dataTableSchema, cmdDelete, pars, aDelta);
        }

        if (aProcessInserts)
        {
            if ((InsertCommandName.Length > 0))// && (!IgnoreStaticCommands))
            {
                cmdInsert = aServiceSchema.NewCommand(aCon, InsertCommandName);
                pars = aServiceSchema.Commands[InsertCommandName].Parameters;
            }
            else
            {
                cmdInsert = CreateUpdateCommand(aCon, dataTableSchema, RemObjects.DataAbstract.ChangeType.Insert, null, UpdateMode, null, out pars);
            }

            mapInsert = CustomCreateParameterMappings(aCon, dataTableSchema, cmdInsert, pars, aDelta);
        }

        if (aProcessUpdates)
        {
            if ((UpdateCommandName.Length > 0))// && (!IgnoreStaticCommands))
            {
                cmdUpdate = aServiceSchema.NewCommand(aCon, UpdateCommandName);
                pars = aServiceSchema.Commands[UpdateCommandName].Parameters;
            }
            else
            {
                cmdUpdate = CreateUpdateCommand(aCon, dataTableSchema, RemObjects.DataAbstract.ChangeType.Update, null, UpdateMode, null, out pars);
            }

            mapUpdate = CustomCreateParameterMappings(aCon, dataTableSchema, cmdUpdate, pars, aDelta);
        }

        if (PrepareCommands)
        {
            //DoPrepareCommands(new System.Data.IDbCommand[] { cmdDelete, cmdInsert, cmdUpdate });
        }

        // Can't do this event
        //if (this.BeforeProcessDelta != null)
        //{
        //    DeltaEventArgs processDelta = new DeltaEventArgs(this, aDelta);
        //    BeforeProcessDelta(this, processDelta);
        //}

        int i = 0;
        bool IsCorrectType;
        while (i < aDelta.Count)
        {
            IsCorrectType = false;
            switch (aDelta[i].Type)
            {
                case RemObjects.DataAbstract.ChangeType.Delete:
                    {
                        if (aProcessDeletes)
                        {
                            curCommand = cmdDelete;
                            curMap = mapDelete;
                            IsCorrectType = true;
                        }
                    }
                    ; break;
                case RemObjects.DataAbstract.ChangeType.Insert:
                    {
                        if (aProcessInserts)
                        {
                            curCommand = cmdInsert;
                            curMap = mapInsert;
                            IsCorrectType = true;
                        }
                    }
                    ; break;
                case RemObjects.DataAbstract.ChangeType.Update:
                    {
                        if (aProcessUpdates)
                        {
                            curCommand = cmdUpdate;
                            curMap = mapUpdate;
                            IsCorrectType = true;
                        }
                    }
                    ; break;
            }

            if (IsCorrectType)
            {
                CustomAssignChangeValuesToCommand(curCommand, curMap, aDelta[i]);

                try
                {
                    curCommand.ExecuteNonQuery();

                    if (aDelta[i].Type != RemObjects.DataAbstract.ChangeType.Delete)
                    {
                        // lazy
                        if (statement == null)
                        {
                            statement = dataTableSchema.Statements.Find(delegate (SchemaSQLStatement e) { return e.Name.Equals(aCon.Name); });
                            //statement = dataTableSchema.Statements[0];
                        }

                        for (int j = 0; j < curCommand.Parameters.Count; j++)
                        {
                            if (outputArray.Contains(((IDataParameter)curCommand.Parameters[j]).Direction))
                            {
                                valName = ((IDataParameter)curCommand.Parameters[j]).ParameterName;
                                mapping = statement.ColumnMappings.get_ItemByTableField(valName.Replace(parNameSymbol, ""));
                                //aDelta[i].set_OldValues(mapping.DataTableField, aDelta[i].get_NewValues(mapping.DataTableField));
                                //aDelta[i].set_NewValues(mapping.DataTableField, ((System.Data.IDataParameter)curCommand.Parameters[j]).Value);
                                aDelta[i].OldValues[mapping.DataTableField] = aDelta[i].NewValues[mapping.DataTableField];
                                aDelta[i].NewValues[mapping.DataTableField] = ((IDataParameter)curCommand.Parameters[j]).Value;
                            }
                            else
                            {
                                if (((IDataParameter)curCommand.Parameters[j]).Direction == System.Data.ParameterDirection.ReturnValue)
                                {
                                    errorCode = (int)((IDataParameter)curCommand.Parameters[j]).Value;
                                }
                            }
                        }
                    }
                    else
                    {
                        for (int j = 0; j < curCommand.Parameters.Count; j++)
                        {
                            if (((IDataParameter)curCommand.Parameters[j]).Direction == System.Data.ParameterDirection.ReturnValue)
                            {
                                errorCode = (int)((IDataParameter)curCommand.Parameters[j]).Value;
                            }
                        }
                    }

                    if (errorCode < 0)
                    {
                        aDelta[i].Status = RemObjects.DataAbstract.ChangeStatus.Failed;
                        aDelta[i].Message = "Fout tijdens opslaan - Inconsistente Data";
                    }
                    else
                    {
                        // Needed to merge on client side
                        aDelta[i].Status = RemObjects.DataAbstract.ChangeStatus.Resolved;
                    }
                }
                catch (Exception ex)
                {
                    throw new EXLSReconcileError("Fout tijdens opslaan gegevens: " + ex.Message);
                }
            }
            i++;
        } // while
    }
    catch (Exception ex)
    {
        throw new EXLSServerException("Server Exception (CustomProcessDelta): " + ex.Message);
    }
}


} // laten staan

protected ParamMappingCollection CustomCreateParameterMappings(IAbstractConnection aConnection, SchemaDataTable aDataTableSchema, IDbCommand aCommand, SchemaParameterCollection aParameterList, Delta aDelta)
{
  string cmdParamName;
  string fldName;
  int deltaValueIndex;
  IDataParameter adoParam = null;
  ParamMapping mapping = null;
  SchemaSQLStatement daStatement = null;
  ParamMappingCollection result = new ParamMappingCollection();

  try
  {
     daStatement = aDataTableSchema.Statements.Find(delegate (SchemaSQLStatement e) { return e.Name.Equals(aConnection.Name); });

     foreach (SchemaColumnMapping colMapping in daStatement.ColumnMappings)
     {

         cmdParamName = aConnection.DataProviderInfo.ParameterNameSymbol + colMapping.TableField;
         if (aCommand.Parameters.Contains(cmdParamName))
         {
             adoParam = (IDataParameter)aCommand.Parameters[cmdParamName];
             if (colMapping.Name.IndexOf(SqlGenerator.OldParamPrefix) == 0)
             {
                 fldName = colMapping.Name.Substring(4);
                 deltaValueIndex = aDelta.GetFieldIndexInValueArray(fldName);
                 mapping = new ParamMapping(adoParam, ParamMappingType.OldValue, deltaValueIndex);
             }
             else
             {
                 fldName = colMapping.Name;
                 deltaValueIndex = aDelta.GetFieldIndexInValueArray(fldName);
                 mapping = new ParamMapping(adoParam, ParamMappingType.NewValue, deltaValueIndex);
             }
             result.Add(mapping);
         }
         // Rest of this implementation is ommited: we do not consider using GeneratorName for autoincs
     }
   }
 catch (Exception ex)
   {
     throw new EXLSServerException("Server Error: (CustomCreateParameterMappings): " + ex.Message);
   }

 return result;
}

Hi, this behavior changed starting from v10.0.0.1605.

From that version, SchemaSQLStatement was updated so that the connection name is stored in the Connection property instead of Name.

As a result, e.Name is empty when loading from a schema file, which is why the Find predicate no longer matches.

The fix is straightforward — update your code to use e.Connection instead of e.Name (in both places).

In CustomCreateParameterMappings:

// Before:
daStatement = aDataTableSchema.Statements.Find(
delegate (SchemaSQLStatement e) { return e.Name.Equals(aConnection.Name); });

// After (fix):
daStatement = aDataTableSchema.Statements.Find(
delegate (SchemaSQLStatement e) {
return string.Equals(e.Connection, aConnection.Name, StringComparison.OrdinalIgnoreCase);
});

In CustomProcessDelta:
// Before:
statement = dataTableSchema.Statements.Find(
delegate (SchemaSQLStatement e) { return e.Name.Equals(aCon.Name); });

// After (fix):
statement = dataTableSchema.Statements.Find(
delegate (SchemaSQLStatement e) {
return string.Equals(e.Connection, aCon.Name, StringComparison.OrdinalIgnoreCase);
});

Perfect. Thanks for the info.