2013-03-04 14 views
6

Ho scritto un metodo sotto usando reflection per caricare diversi datatables fortemente tipizzati in un'applicazione .NET. Se dovessi eseguire come di seguito, tutto funziona, comprese le eccezioni generate. Ma se uso la porzione commentata (tenendo tutto il resto lo stesso), allora ottengo l'errore Impossibile abilitare i limiti qui descritto: enter link description here.Errore di limitazione del carico DataTable()

Se guardo ciò che è dentro la matrice degli errori, è sempre il seguente:

"Column 'AEDelegateName' does not allow DBNull.Value." 

e l'ItemArray per un errore avrà un aspetto simile:

[0] = {} 
[1] = "Some Value" 

che mi sorprende, dal momento che Mi aspetterei solo 1 colonna in uno script che seleziona 1 colonna e non 2 come quello sopra indicato. Immagino anche che questo sia vicino al problema poiché uno di essi sembra essere nullo.

Il mio script non restituisce null, e posso confermarlo rapidamente e visivamente, così come dire cose come NON NULL nella query che uso.

private void GetData(string query, Component tableAdapter) 
{ 
    OracleCommand command = new OracleCommand(); 
    command.Connection = conn; 
    command.CommandText = query; 
    command.CommandType = CommandType.Text; 
    command.CommandTimeout = 3000; 
    OracleDataReader reader = command.ExecuteReader(CommandBehavior.SingleResult); 
    MethodInfo[] methods = tableAdapter.GetType().GetMethods(); 
    MethodInfo getDataMethod = tableAdapter.GetType().GetMethod("GetData"); 
    DataTable table = (DataTable)getDataMethod.Invoke(tableAdapter, null); 
    Type[] paramTypes = new Type[] { table.GetType() }; 
    MethodInfo updateMethod = tableAdapter.GetType().GetMethod("Update", paramTypes); 
    foreach (DataRow row in table.Rows) 
    { 
     row.Delete(); 
    } 
    //try 
    //{ 
    // if (reader.HasRows) 
    // { 
    //  table.Load(reader, LoadOption.OverwriteChanges, FillErrorHandler); 
    // } 
    //} 
    //catch (Exception e) 
    //{ 
    // DataRow[] errors = table.GetErrors(); 
    //} 
    while (reader.Read()) 
    { 
     try 
     { 
      List<object> newRow = new List<object>(); 
      for (int i = 0; i < reader.FieldCount; ++i) 
      { 
       object currentValue = reader.GetValue(i); 
       Debug.WriteLine("Value: "+currentValue); 
       newRow.Add(currentValue); 
      } 
      table.Rows.Add(newRow.ToArray()); 
     } 
     catch (ConstraintException e) 
     { 
      DataRow[] errors = table.GetErrors(); 
     } 
    }    
    updateMethod.Invoke(tableAdapter, new object[]{table}); 
    reader.Close(); 
} 
+0

Potrebbe descrivere la relazione tra la tabella 'DataTable' e la query eseguita tramite' OracleDataReader'? Ho la sensazione che lo schema per entrambi sia diverso e che 'DataTable.Load()' sovrascriva la definizione attivando così il vincolo. – Caramiriel

+0

quale blocco 'catch' sta facendo la cattura? – radarbob

+0

.... @Camamiriel potrebbe essere sulla strada giusta, ma ho intenzione di prendere un WAG istruito e suggerire di aggiungere 'AcceptChanges()' dopo il ciclo di eliminazione delle righe. – radarbob

risposta

1

Per la documentazione per DataTable.Load Method (IDataReader, LoadOption), ho il sospetto che si può essere verificato il comportamento descritto nel brano qui sotto. Hai controllato il numero di colonne restituite dalla tua query rispetto al numero di colonne sul tuo DataTable? Il nome della colonna restituita dalla query corrisponde al nome della colonna desiderata nel tuo DataTable?

Condizione: Gli schemi sono compatibili, ma lo schema set di risultati caricato contiene meno colonne di quanto non faccia la DataTable.

Comportamento: Se una colonna mancante ha un valore predefinito o definito tipo di dati della colonna è nullable, il metodo Load permette righe da aggiunto, sostituendo il valore assunto o nullo per la colonna mancante. Se non è possibile utilizzare alcun valore predefinito o null, il metodo Load genera un'eccezione. Se non è stato fornito alcun valore predefinito specifico, il metodo Load utilizza il valore null come valore implicito predefinito.

Il tuo codice nel ciclo while è probabilmente funzionante perché non fa alcun tentativo di abbinare lo schema. Riempie semplicemente i valori in modo posizionale e riuscirà finché i tipi sono compatibili, non verranno violati i vincoli e l'array non conterrà più elementi di quanti ne abbiano le colonne.