Я боролся с NullReferenceException и надеюсь, что кто-то здесь сможет указать мне правильное направление. Я пытаюсь создать и заполнить DataTable, а затем показать результаты в элементе управления DataGridView. Далее следует основной код, и выполнение останавливается с исключением NullReferenceException в точке, где я вызываю новый UpdateResults_Delegate. Как ни странно, я могу отследить записи. Rows.Count успешно, прежде чем вернуть его из QueryEventEntries, поэтому я могу хотя бы показать 1) записи не являются пустой ссылкой и 2) DataTable содержит строки данных. Я знаю, что должен делать что-то не так, но я просто не знаю, что.
private void UpdateResults(DataTable entries)
{
dataGridView.DataSource = entries;
}
private void button_Click(object sender, EventArgs e)
{
PerformQuery();
}
private void PerformQuery()
{
DateTime start = new DateTime(dateTimePicker1.Value.Year,
dateTimePicker1.Value.Month,
dateTimePicker1.Value.Day,
0, 0, 0);
DateTime stop = new DateTime(dateTimePicker2.Value.Year,
dateTimePicker2.Value.Month,
dateTimePicker2.Value.Day,
0, 0, 0);
DataTable entries = QueryEventEntries(start, stop);
UpdateResults(entries);
}
private DataTable QueryEventEntries(DateTime start, DateTime stop)
{
DataTable entries = new DataTable();
entries.Columns.AddRange(new DataColumn[] {
new DataColumn("event_type", typeof(Int32)),
new DataColumn("event_time", typeof(DateTime)),
new DataColumn("event_detail", typeof(String))});
using (SqlConnection conn = new SqlConnection(DSN))
{
using (SqlDataAdapter adapter = new SqlDataAdapter(
"SELECT event_type, event_time, event_detail FROM event_log " +
"WHERE event_time >= @start AND event_time <= @stop",
conn))
{
adapter.SelectCommand.Parameters.AddRange(new Object[] {
new SqlParameter("@start", start),
new SqlParameter("@stop", stop)});
adapter.Fill(entries);
}
}
return entries;
}
Обновление
Я хотел бы обобщить и предоставить некоторую дополнительную информацию, которую я узнал из обсуждения здесь и отладки с тех пор, как я первоначально разместил этот вопрос.
Я выполняю рефакторинг старого кода, который извлекает записи из базы данных, собирает эти записи в виде массива, а затем выполняет итерацию по массиву, чтобы заполнять DataGridView строка за строкой. Потоки изначально были реализованы, чтобы компенсировать и поддерживать отзывчивость интерфейса во время ненужного зацикливания. С тех пор я удалил Thread / Invoke; теперь все происходит в одном и том же потоке выполнения (спасибо, Сэм ).
Я пытаюсь заменить медленный, громоздкий подход, используя DataTable, который я могу заполнить DataAdapter, и назначить DataGridView через его свойство DataSource (код выше обновлен).
Я перебрал строки записей DataTable, чтобы убедиться, что таблица содержит ожидаемые данные, прежде чем назначить их в качестве источника данных DataGridView.
foreach (DataRow row in entries.Rows)
{
System.Diagnostics.Trace.WriteLine(
String.Format("{0} {1} {2}", row[0], row[1], row[2]));
}
Одним из столбцов DataGridView является пользовательский DataGridViewColumn для стилизации значения event_type. Я извиняюсь, что не упомянул об этом раньше в оригинальном посте, но я не знал, что это важно для моей проблемы. Я временно преобразовал этот столбец в стандартный элемент управления DataGridViewTextBoxColumn и больше не испытываю исключение.
Поля в DataTable добавляются в список полей, которые были предварительно заданы в представлении «Дизайн» DataGridView. Значения записей заполняются в этих добавленных полях. Когда время выполнения пытается визуализировать ячейку, предоставляется нулевое значение (так как значение, которое должно быть отображено , должно быть , делается так, чтобы пара столбцов была выше).
В свете этого я переименовываю и помечаю тегом вопрос. Я по-прежнему был бы признателен, если бы другие, кто испытал это, могли научить меня, как выполнить связывание DataTable с существующими определениями столбцов DataGridView.