Cosa attiva ConstraintException durante il caricamento di DataSet?
Domanda
Come posso sapere quale colonna e valore sta violando il vincolo? Il messaggio di eccezione non è affatto utile:
Impossibile abilitare i vincoli. Uno o più righe contengono valori che violano chiave non nulla, univoca o esterna vincoli.
Soluzione
C'è una proprietà chiamata RowError che puoi controllare.
Vedi http://dotnetdebug.net/2006/07/ 16 / constraintexception-a-utile-tip /
Modificato per aggiungere questo collegamento che mostra l'iterazione di righe per vedere quali errori contenevano.
http://www.devnewsgroups.net/ gruppo / microsoft.public.dotnet.framework.adonet / topic58812.aspx
Altri suggerimenti
Come molte persone, ho i miei componenti standard di accesso ai dati, che includono metodi per restituire un DataSet. Naturalmente, se viene generata una ConstraintException, il DataSet non viene restituito al chiamante, quindi il chiamante non può verificare la presenza di errori di riga.
Quello che ho fatto è catturare e riproporre ConstraintException in tali metodi, registrando i dettagli dell'errore di riga, come nell'esempio seguente (che utilizza Log4Net per la registrazione):
...
try
{
adapter.Fill(dataTable); // or dataSet
}
catch (ConstraintException)
{
LogErrors(dataTable);
throw;
}
...
private static void LogErrors(DataSet dataSet)
{
foreach (DataTable dataTable in dataSet.Tables)
{
LogErrors(dataTable);
}
}
private static void LogErrors(DataTable dataTable)
{
if (!dataTable.HasErrors) return;
StringBuilder sb = new StringBuilder();
sb.AppendFormat(
CultureInfo.CurrentCulture,
"ConstraintException while filling {0}",
dataTable.TableName);
DataRow[] errorRows = dataTable.GetErrors();
for (int i = 0; (i < MAX_ERRORS_TO_LOG) && (i < errorRows.Length); i++)
{
sb.AppendLine();
sb.Append(errorRows[i].RowError);
}
_logger.Error(sb.ToString());
}
Quando si utilizza un set di dati tipizzato forte e si utilizza Visual Designer (xsd): per accedere a tbl.Rows [0] .RowError , è necessario creare le Fill metodo.
Non puoi utilizzare il metodo Get , poiché la DataTable è istanziata nel codice generato.
Ho aggiunto del codice che ho trovato utile nel debug delle occorrenze di ConstraintException qui
Spero che questo aiuti.
Per i googler che desiderano uno snippet per ottenere maggiori dettagli su ConstraintException:
try
{
ds.EnforceConstraints = true;
}
catch (ConstraintException ex)
{
string details = string.Join("",
ds.Tables.Cast<DataTable>()
.Where(t => t.HasErrors)
.SelectMany(t => t.GetErrors())
.Take(50)
.Select(r => "\n - " + r.Table.TableName + "[" + string.Join(", ", r.Table.PrimaryKey.Select(c => r[c])) + "]: " + r.RowError));
throw new ConstraintException(ex.Message + details);
}