Qu'est-ce qui déclenche ConstraintException lors du chargement de DataSet?
Question
Comment puis-je savoir quelle colonne et quelle valeur enfreignent la contrainte? Le message d'exception n'est pas du tout utile:
Impossible d'activer les contraintes. Un ou plus de lignes contiennent des valeurs violant clé non nulle, unique ou étrangère contraintes.
La solution
Il existe une propriété appelée RowError que vous pouvez vérifier.
Voir http://dotnetdebug.net/2006/07/ 16 / constraintexception-un-conseil-utile /
Modifié pour ajouter ce lien montrant l'itération de lignes pour voir celles qui ont eu des erreurs.
http://www.devnewsgroups.net/ groupe / microsoft.public.dotnet.framework.adonet / topic58812.aspx
Autres conseils
Comme beaucoup de gens, j’ai mes propres composants d’accès aux données standard, qui incluent des méthodes pour renvoyer un DataSet. Bien sûr, si une exception ConstraintException est levée, le DataSet n'est pas renvoyé à l'appelant. L'appelant ne peut donc pas rechercher les erreurs de ligne.
Ce que j'ai fait est de capturer et de rediffuser ConstraintException dans de telles méthodes, en enregistrant les détails d'erreur de ligne, comme dans l'exemple suivant (qui utilise Log4Net pour la journalisation):
...
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());
}
Lorsque vous utilisez un ensemble de données fortement typé et utilisez le concepteur visuel (xsd): pour accéder aux informations tbl.Rows [0] .RowError , vous devez créer le remplissage méthode.
Vous ne pouvez pas utiliser la méthode Get , car le DataTable est instancié dans le code généré.
J'ai ajouté du code que j'ai trouvé utile pour le débogage d'occurrences de ConstraintException ici
J'espère que cela vous aidera.
Pour les utilisateurs qui souhaitent un extrait pour obtenir plus de détails sur l’exception 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);
}