Pregunta

¿Alguien tiene algún consejo para lidiar con las ConstraintExceptions generadas por conjuntos de datos XSD?

Esta es la excepción con el mensaje críptico:

System.Data.ConstraintException : Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.
¿Fue útil?

Solución

Un par de consejos que he encontrado últimamente.

  1. Es mucho mejor usar los métodos TableAdapter FillByDataXXXX() en lugar de los métodos GetDataByXXXX() porque el DataTable pasado al método de relleno se puede interrogar en busca de pistas:

    • DatTable.getErrors () Devuelve una matriz de instancias de DataRow por error
    • Datarow.Rowherror contiene una descripción del error de fila
    • Datarow.getColumnSinError () Devuelve una matriz de instancias de DataColumn por error
  2. Recientemente, incluí un código de interrogación en una subclase de ConstraintException que resultó ser un punto de partida útil para la depuración.

C# Ejemplo de uso:

Example.DataSet.fooDataTable table = new DataSet.fooDataTable();

try
{
    tableAdapter.Fill(table);
}
catch (ConstraintException ex)
{
    // pass the DataTable to DetailedConstraintException to get a more detailed Message property
    throw new DetailedConstraintException("error filling table", table, ex);
}

Producción:

Excepción de restricción detallada:error en el llenado de la tabla
Errores reportados para ConstraintExceptionHelper.DataSet+fooDataTable [foo]
Columnas con errores:[1]
[PRODUCT_ID] - total de filas afectadas:1085
Errores de fila:[4]
[La columna 'PRODUCT_ID' está restringida a ser única.El valor '1' ya está presente.] - total de filas afectadas:1009
[La columna 'PRODUCT_ID' está restringida a ser única.El valor '2' ya está presente.] - total de filas afectadas:20
[La columna 'PRODUCT_ID' está restringida a ser única.El valor '4' ya está presente.] - total de filas afectadas:34
[La columna 'PRODUCT_ID' está restringida a ser única.El valor '6' ya está presente.] - total de filas afectadas:22
----> System.Data.ConstraintException:No se pudieron habilitar las restricciones.Una o más filas contienen valores que violan restricciones no nulas, únicas o de clave externa.

No sé si es demasiado código para incluirlo en una respuesta de Stack Overflow, pero aquí está la clase C# completa.Descargo de responsabilidad:esto funciona para mí, siéntase libre de usarlo/modificarlo según corresponda.

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace ConstraintExceptionHelper
{

    /// <summary>
    /// Subclass of ConstraintException that explains row and column errors in the Message property
    /// </summary>
    public class DetailedConstraintException : ConstraintException
    {

        private const int InitialCountValue = 1;


        /// <summary>
        /// Initialises a new instance of DetailedConstraintException with the specified string and DataTable
        /// </summary>
        /// <param name="message">exception message</param>
        /// <param name="ErroredTable">DataTable in error</param>
        public DetailedConstraintException(string message, DataTable erroredTable)
            : base(message)
        {
            ErroredTable = erroredTable;
        }


        /// <summary>
        /// Initialises a new instance of DetailedConstraintException with the specified string, DataTable and inner Exception
        /// </summary>
        /// <param name="message">exception message</param>
        /// <param name="ErroredTable">DataTable in error</param>
        /// <param name="inner">the original exception</param>
        public DetailedConstraintException(string message, DataTable erroredTable, Exception inner)
            : base(message, inner)
        {
            ErroredTable = erroredTable;
        }


        private string buildErrorSummaryMessage()
        {
            if (null == ErroredTable) { return "No errored DataTable specified"; }
            if (!ErroredTable.HasErrors) { return "No Row Errors reported in DataTable=[" + ErroredTable.TableName + "]"; }

            foreach (DataRow row in ErroredTable.GetErrors())
            {
                recordColumnsInError(row);
                recordRowsInError(row);
            }

            StringBuilder sb = new StringBuilder();

            appendSummaryIntro(sb);
            appendErroredColumns(sb);
            appendRowErrors(sb);

            return sb.ToString();
        }


        private void recordColumnsInError(DataRow row)
        {
            foreach (DataColumn column in row.GetColumnsInError())
            {
                if (_erroredColumns.ContainsKey(column.ColumnName))
                {
                    _erroredColumns[column.ColumnName]++;
                    continue;
                }

                _erroredColumns.Add(column.ColumnName, InitialCountValue);
            }
        }


        private void recordRowsInError(DataRow row)
        {
            if (_rowErrors.ContainsKey(row.RowError))
            {
                _rowErrors[row.RowError]++;
                return;
            }

            _rowErrors.Add(row.RowError, InitialCountValue);
        }


        private void appendSummaryIntro(StringBuilder sb)
        {
            sb.AppendFormat("Errors reported for {1} [{2}]{0}", Environment.NewLine, ErroredTable.GetType().FullName, ErroredTable.TableName);
        }


        private void appendErroredColumns(StringBuilder sb)
        {
            sb.AppendFormat("Columns in error: [{1}]{0}", Environment.NewLine, _erroredColumns.Count);

            foreach (string columnName in _erroredColumns.Keys)
            {
                sb.AppendFormat("\t[{1}] - rows affected: {2}{0}",
                                Environment.NewLine,
                                columnName,
                                _erroredColumns[columnName]);
            }
        }


        private void appendRowErrors(StringBuilder sb)
        {
            sb.AppendFormat("Row errors: [{1}]{0}", Environment.NewLine, _rowErrors.Count);

            foreach (string rowError in _rowErrors.Keys)
            {
                sb.AppendFormat("\t[{1}] - rows affected: {2}{0}",
                                Environment.NewLine,
                                rowError,
                                _rowErrors[rowError]);
            }
        }


        /// <summary>
        /// Get the DataTable in error
        /// </summary>
        public DataTable ErroredTable
        {
            get { return _erroredTable; }
            private set { _erroredTable = value; }
        }


        /// <summary>
        /// Get the original ConstraintException message with extra error information
        /// </summary>
        public override string Message
        {
            get { return base.Message + Environment.NewLine + buildErrorSummaryMessage(); }
        }


        private readonly SortedDictionary<string, int> _rowErrors = new SortedDictionary<string, int>();
        private readonly SortedDictionary<string, int> _erroredColumns = new SortedDictionary<string, int>();
        private DataTable _erroredTable;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top