2008-09-26 10 views
31

¿Cómo puedo averiguar qué columna y qué valor están violando la restricción? El mensaje de excepción no es útil en absoluto:¿Qué dispara a ConstraintException al cargar DataSet?

Error al habilitar las restricciones. Una o más filas contienen valores que infringen restricciones no nulas, únicas o de clave foránea .

+2

Daría más arriba-votos si pudiera. Esta es una espina en mi costado también. –

Respuesta

20

igual que muchas personas, tengo mis propios componentes de acceso de datos estándar, que incluyen métodos para devolver un conjunto de datos. Por supuesto, si se lanza una excepción de restricción, el DataSet no se devuelve a la persona que llama, por lo que la persona que llama no puede verificar si hay errores en la fila.

Lo que he hecho es la captura y ConstraintException volver a lanzar en tales métodos, registrando los detalles del error fila, como en el siguiente ejemplo (que utiliza Log4net para el registro):

... 
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()); 
} 
+0

¡Su método LogErrors es genial! Literalmente me salvó hoy. – Dave

1

he añadido algo de código que yo' he encontrado que es útil en la depuración de ocurrencias de ConstraintException here

Espero que esto ayude.

3

Cuando se utiliza un fuerte conjunto de datos con tipo y utilizó el diseñador visual (xsd): acceder a tbl.Rows [0] .RowError de información, es necesario crear el Llenar método.

Usted no puede utilizar el método Get, ya que la instancia de DataTable se genera dentro del código generado.

+0

como dijiste, necesitas un relleno. Muy extraño; ¿Por qué necesitaría una declaración de relleno cuando solo obtengo algunos datos (selección básica)? En algún lugar dentro de este pensamiento, este método de relleno es utilizado por .net, parece. Después de generar un método de relleno (sin cambios en el resultado) funcionó. – Obelix

1

para que los Googlers que quieren un fragmento para obtener más detalles sobre la 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); 
}