2010-04-28 34 views
10

He estado luchando con una NullReferenceException y espero que alguien aquí pueda orientarme en la dirección correcta. Intento crear y llenar una DataTable y luego mostrar los resultados en un control DataGridView. El código básico sigue, y la ejecución se detiene con una NullReferenceException en el punto donde invoco el nuevo UpdateResults_Delegate. Por extraño que parezca, puedo rastrear entradas. Rows.Count correctamente antes de devolverlo desde QueryEventEntries, para que al menos pueda mostrar 1) entradas no es una referencia nula, y 2) DataTable contiene filas de datos. Sé que tengo que estar haciendo algo mal, pero simplemente no sé qué.C# Vincular DataTable a las definiciones existentes de la columna DataGridView

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; 
} 

actualización

me gustaría resumir y proporcionar alguna información adicional que he aprendido de la discusión aquí y los esfuerzos de depuración desde que Iniciado esta pregunta.

Estoy refactorización código antiguo que recupera los registros de una base de datos, recogidos esos registros como una matriz, y luego reiterado a través de la matriz para rellenar una fila a fila DataGridView. El enhebrado se implementó originalmente para compensar y mantener la IU sensible durante el bucle innecesario. Desde entonces, he eliminado Thread/Invoke; todo ahora ocurre en el mismo hilo de ejecución (gracias, Sam).

Estoy intentando reemplazar el enfoque lento e inmanejable usando un DataTable que puedo llenar con un DataAdapter, y asignarlo a DataGridView a través de su propiedad DataSource (código arriba actualizado).

He iterado a través de las entradas de las filas de DataTable para verificar que la tabla contiene los datos esperados antes de asignarlos como el DataSource de DataGridView.

foreach (DataRow row in entries.Rows) 
{ 
    System.Diagnostics.Trace.WriteLine(
     String.Format("{0} {1} {2}", row[0], row[1], row[2])); 
} 

Uno de la columna del DataGridView es una DataGridViewColumn personalizada para estilizar el valor EVENT_TYPE. Me disculpo por no haber mencionado esto antes en la publicación original, pero no sabía que era importante para mi problema. He convertido esta columna temporalmente en un control DataGridViewTextBoxColumn estándar y ya no estoy experimentando la excepción.

Los campos en el DataTable se anexan a la lista de campos que se han especificado previamente en la vista Diseño de DataGridView. Los valores de los registros se están llenando en estos campos adjuntos. Cuando el tiempo de ejecución intenta hacer que la célula se proporciona un valor nulo (como el valor que debería ser prestados se lleva a cabo por lo que un par de columnas sobre).

En vista de esto, estoy volviendo a titular y volver a etiquetar la pregunta. Todavía agradecería que otros que hayan experimentado esto me puedan instruir sobre cómo hacer para vincular DataTable a las definiciones de columnas existentes de DataGridView.

+0

¿Por qué estás tratando de leer desde la base de datos en un hilo separado? –

+0

El código antiguo que estoy tratando de refactorizar se escribió para leer los resultados de la base de datos, repetirlos para llenar una matriz y luego devolver la matriz ... que luego se introdujo en UpdateResults que luego iteraron a través de la matriz y se rellenaron el DataGridView fila por fila. Dependiendo del recuento de filas, esto podría demorar unos segundos y el enhebrado probablemente sea la manera de mantener la GUI en buen estado. – Timothy

+1

No debe actualizar los componentes de la interfaz de usuario de un hilo que no sea de interfaz de usuario. No veo cómo esto podría causar un NRE, debería ser algo más, pero puede estar relacionado. –

Respuesta

24

es necesario asegurarse de la propiedad de cada columna DataPropertyName se establece en el nombre correspondiente de la DataColumn 's ColumnName.

Es posible que también deba establecer la propiedad DataGridViewAutoGenerateColumns en false.

Encontré la solución here.

0

Si el error se produce dentro de UpdateResults, parece que dataGridView es nulo.

private void UpdateResults(DataTable entries) 
{ 
    dataGridView.DataSource = entries; // when is dataGridView set? 
} 
+0

dataGridView está configurado y se muestra en el formulario. Lo coloqué usando el editor de UI en Visual Studio, así como también sus columnas, formateo, etc. – Timothy

+0

@Timothy, entonces, ¿en qué línea ocurre exactamente el error? ¿Cuál es el rastro de la pila completa? ¿Adjuntaste un depurador y visitaste para ver lo que es nulo? –

+0

Intenté refactorizar el código en otra parte de la aplicación de la misma manera que era similar, aunque uno de los elementos que estoy agregando a dataTable es un tipo de datos personalizado. entries.Columns.Add ("colCustType", typeof (CustDataType)); CustDataType ct = new CustDataType(); ct.Property = result.GetInt32 (2); entries.Rows.Add (..., ct, ...); Aquí obtengo el NRE más adelante en la ruta de ejecución en el método de pintura personalizado de dgvCell. ¿Tal vez son similares? También hay una dgvCell personalizada en la primera tabla y tal vez no pueda identificar correctamente dónde se produce la excepción debido al enhebrado. – Timothy

Cuestiones relacionadas