tutorial net mvc homepage framework first español c# entity-framework

c# - net - DbEntityValidationException-¿Cómo puedo saber fácilmente qué causó el error?



entity framework database first español (9)

Como indicó Martin, hay más información en el DbEntityValidationResult . Encontré útil obtener tanto el nombre de mi clase de POCO como el nombre de la propiedad en cada mensaje, y quería evitar tener que escribir atributos de ErrorMessage personalizados en todas mis etiquetas [Required] solo para esto.

La siguiente modificación del código de Martin se encargó de estos detalles por mí:

// Retrieve the error messages as a list of strings. List<string> errorMessages = new List<string>(); foreach (DbEntityValidationResult validationResult in ex.EntityValidationErrors) { string entityName = validationResult.Entry.Entity.GetType().Name; foreach (DbValidationError error in validationResult.ValidationErrors) { errorMessages.Add(entityName + "." + error.PropertyName + ": " + error.ErrorMessage); } }

Tengo un proyecto que utiliza Entity Framework. Al llamar a SaveChanges en mi DbContext , obtengo la siguiente excepción:

System.Data.Entity.Validation.DbEntityValidationException: Error de validación para una o más entidades. Vea la propiedad ''EntityValidationErrors'' para más detalles.

Todo esto está muy bien, pero no quiero adjuntar un depurador cada vez que se produce esta excepción. Además, en los entornos de producción no puedo adjuntar fácilmente un depurador, por lo que tengo que hacer un gran esfuerzo para reproducir estos errores.

¿Cómo puedo ver los detalles ocultos dentro de la DbEntityValidationException ?


Creo que "los errores de validación reales" pueden contener información confidencial, y esta podría ser la razón por la que Microsoft eligió colocarlos en otro lugar (propiedades). La solución marcada aquí es práctica, pero debe tomarse con precaución.

Preferiría crear un método de extensión. Más razones para esto:

  • Mantener rastro de pila original
  • Siga el principio de abrir / cerrar (es decir, puedo usar diferentes mensajes para diferentes tipos de registros)
  • En entornos de producción podría haber otros lugares (es decir, otro dbcontext) donde se podría lanzar una DbEntityValidationException.

En realidad, esto es solo el problema de la validación, EF validará las propiedades de la entidad antes de realizar cambios en la base de datos. Entonces, EF verificará si el valor de la propiedad está fuera del rango, como cuando diseñó la tabla. Table_Column_UserName es varchar (20). Pero, en EF, ingresó un valor mayor a 20. O, en otros casos, si la columna no permite ser un valor nulo. Por lo tanto, en el proceso de validación, debe establecer un valor en la columna no nula, sin importar si va a realizar el cambio en ella. Personalmente, como la respuesta de Leniel Macaferi. Puede mostrarle el detalle de los problemas de validación.


La solución más fácil es anular SaveChanges en su clase de entidades. Puede capturar la DbEntityValidationException , desenvolver los errores reales y crear una nueva DbEntityValidationException con el mensaje mejorado.

  1. Cree una clase parcial junto a su archivo SomethingSomething.Context.cs.
  2. Usa el código al final de esta publicación.
  3. Eso es. Su implementación utilizará automáticamente la anulación de SaveChanges sin ningún trabajo de refactor.

Su mensaje de excepción ahora se verá así:

System.Data.Entity.Validation.DbEntityValidationException: Error de validación para una o más entidades. Vea la propiedad ''EntityValidationErrors'' para más detalles. Los errores de validación son: El campo Número de teléfono debe ser una cadena o tipo de matriz con una longitud máxima de ''12''; El campo Apellido es obligatorio.

Puede eliminar los SaveChanges anulados en cualquier clase que hereda de DbContext :

public partial class SomethingSomethingEntities { public override int SaveChanges() { try { return base.SaveChanges(); } catch (DbEntityValidationException ex) { // Retrieve the error messages as a list of strings. var errorMessages = ex.EntityValidationErrors .SelectMany(x => x.ValidationErrors) .Select(x => x.ErrorMessage);      // Join the list to a single string. var fullErrorMessage = string.Join("; ", errorMessages);      // Combine the original exception message with the new one. var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);      // Throw a new DbEntityValidationException with the improved exception message. throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors); } } }

La DbEntityValidationException también contiene las entidades que causaron los errores de validación. Por lo tanto, si necesita más información, puede cambiar el código anterior para generar información sobre estas entidades.

Véase también: http://devillers.nl/improving-dbentityvalidationexception/


Mientras se encuentra en modo de depuración dentro del bloque catch {...} , abra la ventana "QuickWatch" ( ctrl + alt + q ) y péguelo allí:

((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors

Esto le permitirá profundizar en el árbol de ValidationErrors . Es la forma más fácil que he encontrado para obtener una visión instantánea de estos errores.

Para los usuarios de Visual 2012+ que solo se preocupan por el primer error y pueden no tener un bloque catch , incluso puede hacerlo:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage


Para Azure Functions usamos esta extensión simple para Microsoft.Extensions.Logging.ILogger

public static class LoggerExtensions { public static void Error(this ILogger logger, string message, Exception exception) { if (exception is DbEntityValidationException dbException) { message += "/nValidation Errors: "; foreach (var error in dbException.EntityValidationErrors.SelectMany(entity => entity.ValidationErrors)) { message += $"/n * Field name: {error.PropertyName}, Error message: {error.ErrorMessage}"; } } logger.LogError(default(EventId), exception, message); } }

y ejemplo de uso:

try { do something with request and EF } catch (Exception e) { log.Error($"Failed to create customer due to an exception: {e.Message}", e); return await StringResponseUtil.CreateResponse(HttpStatusCode.InternalServerError, e.Message); }


Para encontrar rápidamente un mensaje de error significativo inspeccionando el error durante la depuración:

  • Añadir un reloj rápido para:

    ((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

  • Profundice en EntityValidationErrors como esto:

    (artículo de colección, por ejemplo, [0])> ValidationErrors> (artículo de colección, por ejemplo [0])> ErrorMessage


Para ver la colección EntityValidationErrors , agregue la siguiente expresión Watch a la ventana Watch.

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

Estoy usando visual studio 2013


Usa el bloque try en tu código como

try { // Your code... // Could also be before try if you know the exception occurs in SaveChanges context.SaveChanges(); } catch (DbEntityValidationException e) { foreach (var eve in e.EntityValidationErrors) { Console.WriteLine("Entity of type /"{0}/" in state /"{1}/" has the following validation errors:", eve.Entry.Entity.GetType().Name, eve.Entry.State); foreach (var ve in eve.ValidationErrors) { Console.WriteLine("- Property: /"{0}/", Error: /"{1}/"", ve.PropertyName, ve.ErrorMessage); } } throw; }

Puedes ver los detalles aquí también

  1. http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/

  2. La validación falló para una o más entidades. Vea la propiedad ''EntityValidationErrors'' para más detalles

  3. http://blogs.infosupport.com/improving-dbentityvalidationexception/