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

804

Tengo este error al sembrar mi base de datos con el primer enfoque de código.

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

Para ser honesto, no sé cómo verificar el contenido de los errores de validación. Visual Studio me muestra que es una matriz con 8 objetos, entonces 8 errores de validación.

Esto funcionaba con mi modelo anterior, pero hice algunos cambios que explico a continuación:

  • Tenía una enumeración llamada Estado, la cambié a una clase llamada Estado
  • Cambié la clase ApplicantsPositionHistory para tener 2 claves foráneas en la misma tabla

Disculpe por el código largo, pero tengo que pegarlo todo. La excepción se produce en la última línea del siguiente código.

namespace Data.Model
{  
    public class Position
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]   
        public int PositionID { get; set; }

        [Required(ErrorMessage = "Position name is required.")]
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Name should not be longer than 20 characters.")]
        [Display(Name = "Position name")]              
        public string name { get; set; }

        [Required(ErrorMessage = "Number of years is required")] 
        [Display(Name = "Number of years")]        
        public int yearsExperienceRequired { get; set; }

        public virtual ICollection<ApplicantPosition> applicantPosition { get; set; }
    }

    public class Applicant
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]      
        public int ApplicantID { get; set; }

        [Required(ErrorMessage = "Name is required")] 
        [StringLength(20, MinimumLength = 3, ErrorMessage="Name should not be longer than 20 characters.")]
        [Display(Name = "First and LastName")]
        public string name { get; set; }

        [Required(ErrorMessage = "Telephone number is required")] 
        [StringLength(10, MinimumLength = 3, ErrorMessage = "Telephone should not be longer than 20 characters.")]
        [Display(Name = "Telephone Number")]
        public string telephone { get; set; }

        [Required(ErrorMessage = "Skype username is required")] 
        [StringLength(10, MinimumLength = 3, ErrorMessage = "Skype user should not be longer than 20 characters.")]
        [Display(Name = "Skype Username")]
        public string skypeuser { get; set; }

        public byte[] photo { get; set; }

        public virtual ICollection<ApplicantPosition> applicantPosition { get; set; }
    }

    public class ApplicantPosition
    {
        [Key]
        [Column("ApplicantID", Order = 0)]
        public int ApplicantID { get; set; }

        [Key]
        [Column("PositionID", Order = 1)]
        public int PositionID { get; set; }

        public virtual Position Position { get; set; }

        public virtual Applicant Applicant { get; set; }

        [Required(ErrorMessage = "Applied date is required")] 
        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date applied")]     
        public DateTime appliedDate { get; set; }

        [Column("StatusID", Order = 0)]
        public int StatusID { get; set; }

        public Status CurrentStatus { get; set; }

        //[NotMapped]
        //public int numberOfApplicantsApplied
        //{
        //    get
        //    {
        //        int query =
        //             (from ap in Position
        //              where ap.Status == (int)Status.Applied
        //              select ap
        //                  ).Count();
        //        return query;
        //    }
        //}
    }

    public class Address
    {
        [StringLength(20, MinimumLength = 3, ErrorMessage = "Country should not be longer than 20 characters.")]
        public string Country { get; set; }

        [StringLength(20, MinimumLength = 3, ErrorMessage = "City  should not be longer than 20 characters.")]
        public string City { get; set; }

        [StringLength(50, MinimumLength = 3, ErrorMessage = "Address  should not be longer than 50 characters.")]
        [Display(Name = "Address Line 1")]     
        public string AddressLine1 { get; set; }

        [Display(Name = "Address Line 2")]
        public string AddressLine2 { get; set; }   
    }

    public class ApplicationPositionHistory
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
        public int ApplicationPositionHistoryID { get; set; }

        public ApplicantPosition applicantPosition { get; set; }

        [Column("oldStatusID")]
        public int oldStatusID { get; set; }

        [Column("newStatusID")]
        public int newStatusID { get; set; }

        public Status oldStatus { get; set; }

        public Status newStatus { get; set; }

        [StringLength(500, MinimumLength = 3, ErrorMessage = "Comments  should not be longer than 500 characters.")]
        [Display(Name = "Comments")]
        public string comments { get; set; }

        [DisplayFormat(DataFormatString = "{0:d}", ApplyFormatInEditMode = true)]
        [Display(Name = "Date")]     
        public DateTime dateModified { get; set; }
    }

    public class Status
    {
        [DatabaseGenerated(System.ComponentModel.DataAnnotations.DatabaseGeneratedOption.Identity)]
        public int StatusID { get; set; }

        [StringLength(20, MinimumLength = 3, ErrorMessage = "Status  should not be longer than 20 characters.")]
        [Display(Name = "Status")]
        public string status { get; set; }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.IO;

namespace Data.Model
{
    public class HRContextInitializer : DropCreateDatabaseAlways<HRContext>
    {
        protected override void Seed(HRContext context)
        {
            #region Status
            Status applied = new Status() { status = "Applied" };
            Status reviewedByHR = new Status() { status = "Reviewed By HR" };
            Status approvedByHR = new Status() { status = "Approved by HR" };
            Status rejectedByHR = new Status() { status = "Rejected by HR" };
            Status assignedToTechnicalDepartment = new Status() { status = "Assigned to Technical Department" };
            Status approvedByTechnicalDepartment = new Status() { status = "Approved by Technical Department" };
            Status rejectedByTechnicalDepartment = new Status() { status = "Rejected by Technical Department" };

            Status assignedToGeneralManager = new Status() { status = "Assigned to General Manager" };
            Status approvedByGeneralManager = new Status() { status = "Approved by General Manager" };
            Status rejectedByGeneralManager = new Status() { status = "Rejected by General Manager" };

            context.Status.Add(applied);
            context.Status.Add(reviewedByHR);
            context.Status.Add(approvedByHR);
            context.Status.Add(rejectedByHR);
            context.Status.Add(assignedToTechnicalDepartment);
            context.Status.Add(approvedByTechnicalDepartment);
            context.Status.Add(rejectedByTechnicalDepartment);
            context.Status.Add(assignedToGeneralManager);
            context.Status.Add(approvedByGeneralManager);
            context.Status.Add(rejectedByGeneralManager); 
            #endregion    

            #region Position
            Position netdeveloper = new Position() { name = ".net developer", yearsExperienceRequired = 5 };
            Position javadeveloper = new Position() { name = "java developer", yearsExperienceRequired = 5 };
            context.Positions.Add(netdeveloper);
            context.Positions.Add(javadeveloper); 
            #endregion

            #region Applicants
            Applicant luis = new Applicant()
            {
                name = "Luis",
                skypeuser = "le.valencia",
                telephone = "0491732825",
                photo = File.ReadAllBytes(@"C:\Users\LUIS.SIMBIOS\Documents\Visual Studio 2010\Projects\SlnHR\HRRazorForms\Content\pictures\1.jpg")
            };

            Applicant john = new Applicant()
            {
                name = "John",
                skypeuser = "jo.valencia",
                telephone = "3435343543",
                photo = File.ReadAllBytes(@"C:\Users\LUIS.SIMBIOS\Documents\Visual Studio 2010\Projects\SlnHR\HRRazorForms\Content\pictures\2.jpg")
            };

            context.Applicants.Add(luis);
            context.Applicants.Add(john); 
            #endregion

            #region ApplicantsPositions
            ApplicantPosition appicantposition = new ApplicantPosition()
            {
                Applicant = luis,
                Position = netdeveloper,
                appliedDate = DateTime.Today,
                StatusID = 1
            };

            ApplicantPosition appicantposition2 = new ApplicantPosition()
            {
                Applicant = john,
                Position = javadeveloper,
                appliedDate = DateTime.Today,
                StatusID = 1
            };        

            context.ApplicantsPositions.Add(appicantposition);            
            context.ApplicantsPositions.Add(appicantposition2); 
            #endregion

            context.SaveChanges(); --->> Error here
        }
    }
}
Luis Valencia
fuente

Respuestas:

1237

Para ser honesto, no sé cómo verificar el contenido de los errores de validación. Visual Studio me muestra que es una matriz con 8 objetos, entonces 8 errores de validación.

En realidad, debería ver los errores si profundiza en esa matriz en Visual Studio durante la depuración. Pero también puede detectar la excepción y luego escribir los errores en algún almacén de registro o en la consola:

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;
}

EntityValidationErrorses una colección que representa las entidades que no se pudieron validar con éxito, y la colección interna ValidationErrorspor entidad es una lista de errores a nivel de propiedad.

Estos mensajes de validación suelen ser lo suficientemente útiles como para encontrar el origen del problema.

Editar

Algunas pequeñas mejoras:

El valor de la propiedad infractora se puede incluir en el bucle interno de la siguiente manera:

        foreach (var ve in eve.ValidationErrors)
        {
            Console.WriteLine("- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                ve.PropertyName,
                eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName),
                ve.ErrorMessage);
        }

Si bien la depuración Debug.Writepuede ser preferible Console.WriteLineya que funciona en todo tipo de aplicaciones, no solo en aplicaciones de consola (gracias a @Bart por su nota en los comentarios a continuación).

Para las aplicaciones web que están en producción y que usan Elmah para el registro de excepciones, resultó ser muy útil para mí crear una excepción personalizada y sobrescribir SaveChangespara lanzar esta nueva excepción.

El tipo de excepción personalizado se ve así:

public class FormattedDbEntityValidationException : Exception
{
    public FormattedDbEntityValidationException(DbEntityValidationException innerException) :
        base(null, innerException)
    {
    }

    public override string Message
    {
        get
        {
            var innerException = InnerException as DbEntityValidationException;
            if (innerException != null)
            {
                StringBuilder sb = new StringBuilder();

                sb.AppendLine();
                sb.AppendLine();
                foreach (var eve in innerException.EntityValidationErrors)
                {
                    sb.AppendLine(string.Format("- Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                        eve.Entry.Entity.GetType().FullName, eve.Entry.State));
                    foreach (var ve in eve.ValidationErrors)
                    {
                        sb.AppendLine(string.Format("-- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                            ve.PropertyName,
                            eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName),
                            ve.ErrorMessage));
                    }
                }
                sb.AppendLine();

                return sb.ToString();
            }

            return base.Message;
        }
    }
}

Y SaveChangesse puede sobrescribir de la siguiente manera:

public class MyContext : DbContext
{
    // ...

    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException e)
        {
            var newException = new FormattedDbEntityValidationException(e);
            throw newException;
        }
    }
}

Algunas observaciones:

  • La pantalla de error amarilla que muestra Elmah en la interfaz web o en los correos electrónicos enviados (si lo ha configurado) ahora muestra los detalles de validación directamente en la parte superior del mensaje.

  • Sobrescribir la Messagepropiedad en la excepción personalizada en lugar de sobrescribir ToString()tiene el beneficio de que la "pantalla amarilla de la muerte (YSOD)" estándar de ASP.NET también muestra este mensaje. En contraste con Elmah, el YSOD aparentemente no usa ToString(), pero ambos muestran la Messagepropiedad.

  • Al envolver el original DbEntityValidationExceptioncomo excepción interna, se garantiza que el seguimiento de la pila original todavía estará disponible y se muestra en Elmah y YSOD.

  • Al establecer un punto de interrupción en la línea throw newException;, simplemente puede inspeccionar la newException.Messagepropiedad como un texto en lugar de profundizar en las colecciones de validación, lo cual es un poco incómodo y no parece funcionar fácilmente para todos (vea los comentarios a continuación).

Slauma
fuente
87
Profundizar en la excepción no hace nada. ¡Solo dice que hay un DbEntityValidationResult pero no te permite expandirte!
Shumii
30
@Shumii Vea esta respuesta para expandir la excepción.
Cavyn VonDeylen
18
Solo para extender una solución elegante. Es posible que desee anular el método savechanges en su propia clase DbContext, y luego agregar el bloque try catch, donde el bloque try solo intenta guardar (base.SaveChanges ()), y el bloque catch solo captura DbEntityValidationException. De esta manera, no necesita agregarlo en cada lugar donde guarde sus cambios.
Milton
77
Esto me ha salvado el tocino en más de una ocasión. Solo pude votar una vez. Ojalá me dejaran votar por cada vez que he copiado y pegado esto.
Damon Drake
55
+2 para el código. De hecho un salvador :) -1 para el uso Console.WriteLine, estimo más personas están escribiendo proyectos web a continuación consola aplicaciones hoy en día, y Debug.Writefunciona tanto en ...
Bart
459

Puede hacerlo desde Visual Studio durante la depuración sin escribir ningún código, ni siquiera un bloque catch.

Simplemente agregue un reloj con el nombre:

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

La expresión de observación $exceptionmuestra cualquier excepción lanzada en el contexto actual, incluso si no se ha detectado y asignado a una variable.

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

Yoel Halb
fuente
39
Solución de +1 mucho mejor, y no requiere cambios en el código. Genial
Justas
44
¡+1 esto es muy, muy útil! Ni siquiera necesita tener un bloque try / catch. Solo pegue esto en la lista de observación cuando VS se rompa y listo ... tiene los errores de validación frente a usted.
theyetiman
40
un par de veces al año se me olvida cómo hacer esto y encuentro esta respuesta
Justin Moore
3
@zairja No lo he probado en vb.net, pero parece que la variable también está definida para vb.net en msdn.microsoft.com/en-us/library/ms164891.aspx , sin embargo, el reparto probablemente no sea definido para vb.net, y en su lugar, probablemente debería hacer DirectCast ($ excepción, System.Data.Entity.Validation.DbEntityValidationException)
yoel halb
2
Sé que "gracias" no son bienvenidos en los comentarios, pero en aras de evitarme horas de tiempo perdido ... ¡gracias!
Luther
105

Esto podría hacerlo sin tener que escribir código:

En su bloque catch, agregue un punto de interrupción en la siguiente línea de código:

catch (Exception exception)
{

}

Ahora, si pasa el cursor exceptiono lo agrega al Watchy luego navega a los detalles de la excepción como se muestra a continuación; verá qué columna (s) en particular está causando el problema, ya que este error generalmente ocurre cuando se viola una restricción de tabla.

ingrese la descripción de la imagen aquí

Imagen grande

t_plusplus
fuente
44
Este enfoque es muy simple y aprovecha el IDE :)
dsnunez
3
Esta es una buena solución porque es rápida, simple, hace uso del IDE y me ahorró un montón de tiempo.
maxshuty
2
Me gusta así "Cómo ser un codificador y no hacer código"
abierto y gratuito el
1
Gracias. Esto es simple pero es impresionante ver la excepción usando IDE.
Thomas.Benz
solución perfecta
Neeraj Singh Chouhan
46

Aquí le mostramos cómo puede verificar el contenido de los EntityValidationErrors en Visual Studio (sin escribir ningún código adicional), es decir, durante la depuración en el IDE .

¿El problema?

Tiene razón, la ventana emergente Ver detalles del depurador de Visual Studio no muestra los errores reales dentro de la EntityValidationErrorscolección.

ingrese la descripción de la imagen aquí

¡La solución!

Simplemente agregue la siguiente expresión en una ventana de Vista rápida y haga clic en Reevaluar .

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

En mi caso, vea cómo puedo expandirme ValidationErrors Listdentro de la EntityValidationErrorscolección.

ingrese la descripción de la imagen aquí

Referencias: publicación de blog mattrandle.me , respuesta de @yoel

Shiva
fuente
3
¿Por qué esto no se ha solucionado? debería mostrar el error, no otra cosa
Geomorillo
2
El error de validación muestra el error de propiedad, ej. campo de asunto es obligatorio, buena respuesta, gracias
hamzeh.hanandeh
1
¡Excelente! ¡Me salvó la noche! :)
Patrick
1
esta es una forma inteligente de visualizar el error exacto en el reloj ... ¡gracias!
Qwerty
39

Para una forma rápida de ver el primer error sin siquiera agregar un reloj, puede pegar esto en la Ventana Inmediata:

((System.Data.Entity.Validation.DbEntityValidationException)$exception)
    .EntityValidationErrors.First()
    .ValidationErrors.First()
djdmbrwsk
fuente
1
También puede usar $ exception.EntityValidationErrors.SelectMany (x => x.ValidationErrors) .Seleccione (x => x.ErrorMessage) para obtenerlos :) imho usando la ventana inmediata es la mejor respuesta
chrispepper1989
15

Para cualquiera que trabaje en VB.NET

Try
Catch ex As DbEntityValidationException
    For Each a In ex.EntityValidationErrors
        For Each b In a.ValidationErrors
            Dim st1 As String = b.PropertyName
            Dim st2 As String = b.ErrorMessage
        Next
    Next
End Try
nghiavt
fuente
12

Mientras está en modo de depuración dentro del catch {...}bloque, abra la ventana "QuickWatch" ( ctrl+ alt+ q) y pegue allí:

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

o:

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

Si no está en un try / catch o no tiene acceso al objeto de excepción.

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

GONeale
fuente
10

Si simplemente está detectando una excepción genérica, puede ser beneficioso lanzar esto como una excepción DbEntityValidationException . Este tipo de excepción tiene una propiedad de Errores de validación, y si continúa expandiéndose hacia ellos, encontrará todos los problemas.

Por ejemplo, si coloca un punto de interrupción en la captura, puede lanzar lo siguiente en un reloj:

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

Un ejemplo de error es si un campo no permite valores nulos y tiene una cadena nula, verá que dice que el campo es obligatorio.

Greg
fuente
9

solo verifique la longitud del campo de la tabla de la base de datos. Su texto de entrada es mayor que la longitud del tipo de datos del campo de columna

Hardeep Singh
fuente
9

En la depuración, puede ingresar esto en su campo de entrada del evaluador de expresiones QuickWatch:

context.GetValidationErrors()
silverfox1948
fuente
8

La respuesta de @Slauma es realmente genial, pero descubrí que no funcionaba cuando una propiedad ComplexType no era válida.

Por ejemplo, supongamos que tiene una propiedad Phonedel tipo complejo PhoneNumber. Si la AreaCodepropiedad no es válida, el nombre de la propiedad ve.PropertyNameses "Phone.AreaCode". Esto hace que la llamada eve.Entry.CurrentValues<object>(ve.PropertyName)falle.

Para solucionar esto, puede dividir el nombre de la propiedad en cada uno ., luego recurrir a la matriz resultante de nombres de propiedades. Finalmente, cuando llegue al final de la cadena, simplemente puede devolver el valor de la propiedad.

A continuación se muestra la FormattedDbEntityValidationExceptionclase de @ Slauma con soporte para ComplexTypes.

¡Disfrutar!

[Serializable]
public class FormattedDbEntityValidationException : Exception
{
    public FormattedDbEntityValidationException(DbEntityValidationException innerException) :
        base(null, innerException)
    {
    }

    public override string Message
    {
        get
        {
            var innerException = InnerException as DbEntityValidationException;
            if (innerException == null) return base.Message;

            var sb = new StringBuilder();

            sb.AppendLine();
            sb.AppendLine();
            foreach (var eve in innerException.EntityValidationErrors)
            {
                sb.AppendLine(string.Format("- Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
                    eve.Entry.Entity.GetType().FullName, eve.Entry.State));
                foreach (var ve in eve.ValidationErrors)
                {
                    object value;
                    if (ve.PropertyName.Contains("."))
                    {
                        var propertyChain = ve.PropertyName.Split('.');
                        var complexProperty = eve.Entry.CurrentValues.GetValue<DbPropertyValues>(propertyChain.First());
                        value = GetComplexPropertyValue(complexProperty, propertyChain.Skip(1).ToArray());
                    }
                    else
                    {
                        value = eve.Entry.CurrentValues.GetValue<object>(ve.PropertyName);
                    }
                    sb.AppendLine(string.Format("-- Property: \"{0}\", Value: \"{1}\", Error: \"{2}\"",
                        ve.PropertyName,
                        value,
                        ve.ErrorMessage));
                }
            }
            sb.AppendLine();

            return sb.ToString();
        }
    }

    private static object GetComplexPropertyValue(DbPropertyValues propertyValues, string[] propertyChain)
    {
        var propertyName = propertyChain.First();
        return propertyChain.Count() == 1 
            ? propertyValues[propertyName] 
            : GetComplexPropertyValue((DbPropertyValues)propertyValues[propertyName], propertyChain.Skip(1).ToArray());
    }
}
mikesigs
fuente
1
No puedo creer que más personas no hayan votado por este, ya que es un escenario muy real y me ha vuelto loco las últimas dos noches. ¿Sabes lo que sientes cuando te das cuenta de que tu manejo de errores es lo que realmente arroja el error? Ugh
DJ Grossman
7

Tenga en cuenta que Entity.GetType().BaseType.Nameda el nombre de tipo que especificó, no el que tiene todos los dígitos hexadecimales en su nombre.

Eric Nelson
fuente
7

Según la respuesta de @ Slauma y la sugerencia de @ Milton, extendí el método de guardado personalizado de nuestra clase base con un try / catch que manejará (¡y por lo tanto iniciará sesión en nuestro registro de errores!) Este tipo de excepciones.

// Where `BaseDB` is your Entities object... (it could be `this` in a different design)
public void Save(bool? validateEntities = null)
{
    try
    {
        //Capture and set the validation state if we decide to
        bool validateOnSaveEnabledStartState = BaseDB.Configuration.ValidateOnSaveEnabled;
        if (validateEntities.HasValue)
            BaseDB.Configuration.ValidateOnSaveEnabled = validateEntities.Value;

        BaseDB.SaveChanges();

        //Revert the validation state when done
        if (validateEntities.HasValue)
            BaseDB.Configuration.ValidateOnSaveEnabled = validateOnSaveEnabledStartState;
    }
    catch (DbEntityValidationException e)
    {
        StringBuilder sb = new StringBuilder();
        foreach (var eve in e.EntityValidationErrors)
        {
            sb.AppendLine(string.Format("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)
            {
                sb.AppendLine(string.Format("- Property: \"{0}\", Error: \"{1}\"",
                                            ve.PropertyName,
                                            ve.ErrorMessage));
            }
        }
        throw new DbEntityValidationException(sb.ToString(), e);
    }
}
jocull
fuente
1
Puede usar sb.AppendFormat () directamente
Bastien Vandamme
1
Necesitará agregar su propia nueva línea también si usa AppendFormat.
jocull
7

Tenía que escribir esto en la ventana Inmediato: 3

(((exception as System.Data.Entity.Validation.DbEntityValidationException).EntityValidationErrors as System.Collections.Generic.List<System.Data.Entity.Validation.DbEntityValidationResult>)[0].ValidationErrors as System.Collections.Generic.List<System.Data.Entity.Validation.DbValidationError>)[0]

para profundizar en el error exacto!

Nour Sabouny
fuente
6

Usando la respuesta de @Slauma, he creado un fragmento de código (un borde con fragmento) para un mejor uso.

<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <SnippetTypes>
        <SnippetType>SurroundsWith</SnippetType>
      </SnippetTypes>
      <Title>ValidationErrorsTryCatch</Title>
      <Author>Phoenix</Author>
      <Description>
      </Description>
      <HelpUrl>
      </HelpUrl>
      <Shortcut>
      </Shortcut>
    </Header>
    <Snippet>
      <Code Language="csharp"><![CDATA[try
{
    $selected$ $end$
}
catch (System.Data.Entity.Validation.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;
}]]></Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>
Phoenix_uy
fuente
5

Capture la excepción en un intento de captura y luego en la observación rápida o ctrl + d & ctrl + q y puede profundizar en EntityValidationErrors.

Brandon.Staley
fuente
5

Solo tirando mis dos centavos en ...

Dentro de mi dbConfiguration.cs, me gusta envolver mi método context.SaveChanges () en un try / catch y producir un archivo de texto de salida que me permite leer el Error (s) claramente, y este código también los marca de tiempo, útil si usted ¡encuentre más de un error en diferentes momentos!

        try
        {
            context.SaveChanges();
        }
        catch (DbEntityValidationException e)
        {
            //Create empty list to capture Validation error(s)
            var outputLines = new List<string>();

            foreach (var eve in e.EntityValidationErrors)
            {
                outputLines.Add(
                    $"{DateTime.Now}: Entity of type \"{eve.Entry.Entity.GetType().Name}\" in state \"{eve.Entry.State}\" has the following validation errors:");
                outputLines.AddRange(eve.ValidationErrors.Select(ve =>
                    $"- Property: \"{ve.PropertyName}\", Error: \"{ve.ErrorMessage}\""));
            }
            //Write to external file
            File.AppendAllLines(@"c:\temp\dbErrors.txt", outputLines);
            throw;
        }
IfElse TryCatch
fuente
5

Lo que encontré ... cuando recibí el error 'EntityValidationErrors' es que ... tengo un campo en mi base de datos 'db1' en la tabla 'tbladdress' como 'address1' que tiene un tamaño de 100 (es decir, la dirección varchar (100) nulo) y estaba pasando un valor de más de 100 caracteres ... y esto condujo a un error al guardar datos en la base de datos ...

Por lo tanto, debe Verificar los datos que está pasando al campo.

Dharmendra Prajapati
fuente
1
Agradezco esta respuesta porque en realidad me ayudó a resolver mi error. La tabla en la que estaba guardando en mi base de datos tenía todas las not nullcolumnas, por lo que una vez que agregué datos a todos los elementos antes de mi db.SaveChanges()no recibí ningún error.
BinaryJoe01
3

Esto funciona para mi.

var modelState = ModelState.Values;
if (!ModelState.IsValid)
{
    return RedirectToAction("Index", "Home", model);
}

Ponga un punto de interrupción en la declaración if. Luego puede verificar modelState en las ventanas de depuración. En cada valor puede ver si hay un error e incluso el mensaje de error. Eso es. Cuando ya no lo necesite, simplemente elimine o comente la línea.

Espero que esto sea de ayuda.

Si se me solicita, puedo proporcionar una captura de pantalla detallada en la ventana de depuración.

AngelDown
fuente
3

Como se mencionó en otras publicaciones, simplemente capture la excepción en la clase DbEntityValidationException. Lo que le dará lo que necesite durante los casos de error.

 try
 {
  ....
 }
 catch(DbEntityValidationException ex)
 {
  ....
 }
Mayank
fuente
2

Me enfrenté a este error antes

cuando intenté actualizar un campo específico en mi modelo en el marco de la entidad

Letter letter = new Letter {ID = letterId, ExportNumber = letterExportNumber,EntityState = EntityState.Modified};
LetterService.ChangeExportNumberfor(letter);
//----------


public int ChangeExportNumber(Letter letter)
    {
        int result = 0;
        using (var db = ((LettersGeneratorEntities) GetContext()))
        {
            db.Letters.Attach(letter);
            db.Entry(letter).Property(x => x.ExportNumber).IsModified = true;
            result += db.SaveChanges();
        }
        return result;
    }

y de acuerdo con las respuestas anteriores

Encontré el mensaje de validación The SignerName field is required.

que apunta al campo en mi modelo

y cuando revisé el esquema de mi base de datos encontré

ingrese la descripción de la imagen aquí

así que Coure ValidationExceptiontiene derecho a elevar

y de acuerdo con este campo, quiero que sea anulable (no sé cómo lo ensucié)

así que cambié ese campo para permitir Null, y con esto mi código no me dará este error nuevamente

Este error puede suceder si invalida la integridad de sus datos de su base de datos

Basheer AL-MOMANI
fuente
1
Si se debe plantear o no una excepción no es el punto aquí. A continuación, estás cortando algunas esquinas aquí. Cuando se requiere un campo en el esquema de la base de datos, se necesita más que eso para generar un campo DbEntityValidationException.
Gert Arnold
2

Verifique el valor de los campos que está pasando, son válidos y de acuerdo con los campos de la base de datos. Por ejemplo, el número de caracteres pasados ​​en un campo particular es menor que los caracteres definidos en el campo de la tabla de la base de datos.

arun tiwari
fuente
1

Si está utilizando IIS con autenticación de Windows and Entity Framework , tenga cuidado de usarlo authorize.

Intenté POSTsin autorización y no funcionó, y obtuve este error endb.SaveChangesAsync(); , mientras que todos los demás verbos GETy DELETEestaban funcionando.

Pero cuando agregué AuthorizeAttribute como anotación, funcionó.

[Authorize]
public async Task<IHttpActionResult> Post(...){
....
}
Toodoo
fuente
1

Aquí hay otra forma de hacerlo en lugar de usar bucles foreach para mirar dentro de EntityValidationErrors. Por supuesto, puede formatear el mensaje a su gusto:

try {
        // your code goes here...
    } 
catch (DbEntityValidationException ex) 
    {
        Console.Write($"Validation errors: {string.Join(Environment.NewLine, ex.EntityValidationErrors.SelectMany(vr => vr.ValidationErrors.Select(err => $"{err.PropertyName} - {err.ErrorMessage}")))}", ex);
        throw;
    }
Quantum_Joe
fuente
1

En mi caso fue porque la longitud del campo de la base de datos es menor que la longitud del campo de entrada.

tabla de base de datos

create table user(
  Username nvarchar(5) not  null
);

Mi entrada

User newUser = new User()
{
   Username = "123456"
};

el valor Username lengthes 5, que es lessthan6

... esto puede ayudar a alguien

QWERTY
fuente
0

Verifique si tiene Not Nullrestricciones en las columnas de su tabla y no pasa el valor de esa columna mientras inserta / actualiza las operaciones. Eso causa esta excepción en el marco de la entidad.

s Jagathish
fuente
0

También enfrenté el mismo problema. Actualicé mi .edmx de la base de datos después de que la excepción desapareció.

HariChintha
fuente
0

Este error ocurre principalmente debido al tamaño del campo. COMPRUEBE todos los tamaños de campo en una tabla de base de datos.

Alexander Zaldostanov
fuente
0

También estaba luchando con este error y en función del tema aquí y esta respuesta fue capaz de descifrar fragmentos para copiar / pegar sin la necesidad de averiguar qué se debe importar (excelente para principiantes de C #), código a continuación:

try
{
  context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
  foreach (var entityValidationErrors in ex.EntityValidationErrors)
  {
    foreach (var validationError in entityValidationErrors.ValidationErrors)
    {
      System.Diagnostics.Debug.WriteLine("Property: " + validationError.PropertyName + " Error: " + validationError.ErrorMessage);
    }
  }
}
Daniel Danielecki
fuente