DataView NullReferenceException в OnListChanged
У меня есть довольно сложное приложение WinForms, которое использует привязку данных для привязки строго типизированных DataTables к элементам управления (не уверен, что этот факт имеет значение здесь). Исключение возникает, когда изменение столбца запускает логику, которая обновляет другой столбец в той же строке (или, по крайней мере, это моя теория).
Пример: запись о Клиенте связана с ComboBox со списком контактов для Customer::MarketingContactId. Когда контакт изменится, появятся несколько текстовых полей и флажков, которые будут обновлены, чтобы можно было редактировать данные этого контакта. Один из этих флажков имеет обработчик событий на CheckChanged
void MarketingContactIsFulltimeChangedHandler(object sender, EventArgs e)
{
var contact = m_row.MarketingContact;
if (contact != null && contact.IsFullTimeEmployee)
{
var i = m_row.Institution;
if (i.CreditLevel > m_row.CreditLevel)
m_row.CreditLevel = i.CreditLevel;
}
}
m_row - Клиент, получающий обновления. Ошибка не происходит в этом коде, но на самом деле возникает из настройки поля MarketingContactId. Вот стек вызовов, который подтверждает это:
System.Data.dll! System.Data.DataView.OnListChanged (System.ComponentModel.ListChangedEventArgs e = {System.ComponentModel.ListChangedEventArgs}) Строка 1433 + 0x2c байтов C# System.Data.dll! Object.Dang.DataView.IndexLhC отправитель, System.ComponentModel.ListChangedEventArgs e = {System.ComponentModel.ListChangedEventArgs}) Строка 1299 C# System.Data.dll!System.Data.DataView.IndexListChangedInternal(System.ComponentModel.ListChangedE24SignEvengs)
System.Data.dll! System.Data.DataViewListener.IndexListChanged (System.ComponentModel.ListChangedEventArgs e) Строка 76 + 0x7 байт C#
System.Data.dll! System.Data.Index.OnListChanged.AnonymousMethod (прослушиватель System.Data.DataViewListener, System.ComponentModel.ListChangedEventArgs, аргументы bool arg2, bool arg3) Строка 803 + 0x7 байт C#
System.Data.dll! System.Data.Listeners.Notify (System.ComponentModel.ListChangedEventArgs arg1 = {System.ComponentModel.ListChangedEventArgs}, bool arg2 = false, bool arg3 = false, System.Data.Listeners.Action action = {Метод = {Void b__2(System.Data.DataViewListener, System.ComponentModel.ListChangedEventArgs, Boolean, Boolean)}}) Строка 1029 + 0x1a байтов C# System.Data.dll!System.Data.Index.OnListChanged(System.ComponentModel.LextChist) Строка 805 C# System.Data.dll!System.Data.Index.OnListChanged(System.ComponentModel.ListChangedType updatedType, int newIndex, int oldIndex) Строка 788 C# System.Data.dll!System.Data.Index.RecordStateChanged(int oldRec), System.Data.DataViewRowState oldOldState, System.Data.DataViewRowState oldNewState, int newRecord, System.Data.DataViewRowState newOldState, System.Data.DataViewRowState newNewState) Строка 903 + 0x10 байт C#
System.Data.dll! System.Data.DataTable.RecordStateChanged (int record1 = 0, System.Data.DataViewRowState oldState1 = Добавлено, System.Data.DataViewRowState newState1 = Нет, int record2 = 1, System.Data.DataViewRowState oldState2 = Нет, System.Data.DataViewRowState newState2 = Добавлено) Строка 3473 + 0x18 байт C# System.Data.dll!System.Data.DataTable.SetNewRecordWorker(System.Data.DataRow row = "CustomerRow: Id:-1", int предлагаемый Record, система.Data.DataRowAction action = Change, bool isInMerge, int position, bool fireEvent = true, out System.Exception deferredException = null) Строка 3935 + 0x16 байт C#
System.Data.dll! System.Data.DataTable.SetNewRecord (строка System.Data.DataRow, int предлагаемый Record, System.Data.DataRowAction действие, bool isInMerge, bool fireEvent) Строка 3824 C# System.Data.dll!System.Data.DataRow.SetNewRecord(int record) Строка 1160 C# System.Data.dll!System.Data.DataRow.EndEdit() Строка 631 + 0xa байтов C#
System.Data.dll! System.Data.DataRow.this [System.Data.DataColumn].set (столбец System.Data.DataColumn, значение объекта) Строка 343 C#
Номера строк есть, так как у меня есть символы, загруженные для System.Data.dll из функции MS Symbol Server в Visual Studio. Наличие этих данных позволяет мне далее отслеживать ошибку в этой части метода OnListChanged:
// snippet from System.Data.DataView::OnListChanged(ListChangedEventArgs e)
if (onListChanged != null) {
if ((col != null) && (e.NewIndex == e.OldIndex)) {
ListChangedEventArgs newEventArg = new ListChangedEventArgs(e.ListChangedType, e.NewIndex, new DataColumnPropertyDescriptor(col));
/*Here is where VS breaks for the exception*/ onListChanged(this, newEventArg);
} else {
onListChanged(this, e);
}
}
Очевидно, что-то пошло не так, если только после проверки onListChanged!= Null это так. Я подозреваю, что обновление DataRow во время метода EndEdit вызывает это. Конечно, простая песочница, чтобы изолировать эту проблему, не отображала ошибку для меня. Кто-нибудь еще на SO сталкивался с этой ошибкой, и если да, то как вы ее исправили?
Сейчас я хочу вызвать BeginInvoke в MarketingContactIsFulltimeChangedHandler для другого метода, который выполняет там логику CreditLevel.