Falha na validação para uma ou mais entidades. Consulte a propriedade 'EntityValidationErrors' para obter mais detalhes

804

Estou tendo esse erro ao propagar meu banco de dados com a primeira abordagem de código.

Falha na validação para uma ou mais entidades. Consulte a propriedade 'EntityValidationErrors' para obter mais detalhes.

Para ser sincero, não sei como verificar o conteúdo dos erros de validação. O Visual Studio me mostra que é uma matriz com 8 objetos, portanto 8 erros de validação.

Isso estava funcionando com o meu modelo anterior, mas fiz algumas alterações que explico abaixo:

  • Eu tinha um enum chamado Status, mudei para uma classe chamada Status
  • Alterei a classe ApplicantsPositionHistory para ter 2 chaves estrangeiras na mesma tabela

Desculpe-me pelo código longo, mas tenho que colar tudo. A exceção é lançada na última linha do código a seguir.

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
fonte

Respostas:

1237

Para ser sincero, não sei como verificar o conteúdo dos erros de validação. O Visual Studio me mostra que é uma matriz com 8 objetos, portanto 8 erros de validação.

Na verdade, você deverá ver os erros se detalhar essa matriz no Visual studio durante a depuração. Mas você também pode capturar a exceção e gravar os erros em algum armazenamento de log ou no console:

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

EntityValidationErrorsé uma coleção que representa as entidades que não puderam ser validadas com êxito e a coleção interna ValidationErrorspor entidade é uma lista de erros no nível da propriedade.

Essas mensagens de validação geralmente são úteis o suficiente para encontrar a fonte do problema.

Editar

Algumas pequenas melhorias:

O valor da propriedade incorreta pode ser incluído no loop interno da seguinte maneira:

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

Embora a depuração Debug.Writepossa ser preferível Console.WriteLine, pois funciona em todos os tipos de aplicativos, não apenas nos aplicativos de console (obrigado a @Bart por sua observação nos comentários abaixo).

Para aplicativos da Web que estão em produção e que usam o Elmah para o registro de exceções, foi muito útil criar uma exceção personalizada e sobrescrever SaveChangespara lançar essa nova exceção.

O tipo de exceção personalizado é parecido com este:

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

E SaveChangespode ser substituído da seguinte maneira:

public class MyContext : DbContext
{
    // ...

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

Algumas observações:

  • A tela de erro amarela que Elmah mostra na interface da web ou nos emails enviados (se você tiver configurado isso) agora exibe os detalhes da validação diretamente na parte superior da mensagem.

  • Sobrescrever a Messagepropriedade na exceção personalizada em vez de sobrescrever ToString()tem o benefício de que o ASP.NET "Tela amarela da morte (YSOD)" padrão também exibe essa mensagem. Ao contrário de Elmah, o YSOD aparentemente não usa ToString(), mas ambos exibem a Messagepropriedade.

  • A quebra automática do original DbEntityValidationExceptioncomo exceção interna garante que o rastreamento da pilha original ainda esteja disponível e seja exibido no Elmah e no YSOD.

  • Ao definir um ponto de interrupção na linha, throw newException;você pode simplesmente inspecionar a newException.Messagepropriedade como um texto, em vez de pesquisar nas coleções de validação, o que é um pouco estranho e parece não funcionar facilmente para todos (veja os comentários abaixo).

Slauma
fonte
87
Detalhar a exceção não faz nada. Apenas diz que há um DbEntityValidationResult, mas não permite expandir !!
Shumii 28/08/12
30
@Shumii Veja esta resposta para expandir a exceção.
Cavyn VonDeylen
18
Apenas para ampliar uma solução elegante. Convém substituir o método savechanges em sua própria classe DbContext e adicionar o bloco try catch, onde o bloco try apenas tenta salvar (base.SaveChanges ()) e o bloco catch captura apenas DbEntityValidationException. Dessa forma, você não precisa adicioná-lo em todos os lugares em que salvar suas alterações.
Milton
7
Isso salvou meu bacon em mais de uma ocasião. Só pude votar uma vez. Queria que eles me deixassem votar por toda vez que copiei e colei isso.
Damon Drake
5
+2 para o código. Na verdade um salvador :) -1 para usar Console.WriteLine, eu estimo mais pessoas estão escrevendo projetos web, em seguida, consolar aplicativos hoje em dia, e Debug.Writefunciona em ambos ...
Bart
459

Você pode fazer isso no Visual Studio durante a depuração sem escrever nenhum código, nem mesmo um bloco catch.

Basta adicionar um relógio com o nome:

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

A expressão de observação $exceptionexibe qualquer exceção lançada no contexto atual, mesmo que não tenha sido capturada e atribuída a uma variável.

Com base em http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/

yoel halb
fonte
39
Solução +1 muito melhor e não requer alterações no código. Legal
Justas
4
+1 isso é muito, muito útil! Você nem precisa ter um bloco try / catch. Basta colocar isso na lista de observação quando o VS quebrar e pronto ... você tem os erros de validação à sua frente.
theyetiman
40
um par de vezes por ano eu esquecer como fazer isso e encontrar esta resposta
Justin Moore
3
@zairja Não testei no vb.net, mas parece que a variável também está definida para vb.net no msdn.microsoft.com/en-us/library/ms164891.aspx , no entanto, o elenco provavelmente não é definido para vb.net, e em vez disso você provavelmente deve fazer DirectCast ($ exceção, System.Data.Entity.Validation.DbEntityValidationException)
halb yoel
2
Eu sei que "obrigado" não é bem-vindo nos comentários, mas por uma questão de me impedir horas de tempo perdido ... obrigado!
Luther
105

Na verdade, isso poderia ser feito sem a necessidade de escrever código:

No seu bloco catch, adicione um ponto de interrupção na seguinte linha de código:

catch (Exception exception)
{

}

Agora, se você passar o mouse exceptionou adicioná-lo ao Watche, em seguida, navegue nos detalhes da exceção, como mostrado abaixo; você verá quais colunas específicas estão causando o problema, pois esse erro geralmente ocorre quando uma restrição de tabela é violada.

insira a descrição da imagem aqui

Imagem grande

t_plusplus
fonte
4
Esta abordagem é muito simples e leva vantagem do IDE :)
dsnunez
3
Esta é uma boa solução, porque é rápida, simples, utiliza o IDE e me poupou muito tempo.
Maxhuty #
2
Eu gosto desta maneira "Como ser um codificador e não fazer código"
aberto e gratuito
1
Obrigado. Isso é simples, mas é incrível ver a exceção usando o IDE.
precisa saber é o seguinte
solução perfeita
Neeraj Singh Chouhan 30/09/19
46

Veja como você pode verificar o conteúdo dos EntityValidationErrors no Visual Studio (sem escrever nenhum código extra), ou seja, durante a Depuração no IDE .

O problema?

Você está certo, o pop-up View Details do depurador do Visual Studio não mostra os erros reais dentro da EntityValidationErrorscoleção.

insira a descrição da imagem aqui

A solução!

Basta adicionar a seguinte expressão em uma janela do Quick Watch e clicar em Reavaliar .

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

No meu caso, veja como sou capaz de expandir para ValidationErrors Listdentro da EntityValidationErrorscoleção

insira a descrição da imagem aqui

Referências: postagem no blog mattrandle.me , @ yoel's answer

Shiva
fonte
3
por que isso não foi corrigido? ele deve mostrar o erro não outra coisa
Geomorillo
2
O erro de validação mostra o erro de propriedade, ex. campo de assunto é obrigatório, boa resposta, Obrigado #
hamzeh.hanandeh 15/0218
1
Ótimo! Salvou a minha noite! :)
Patrick
1
esta é uma maneira inteligente de visualizar o erro exato no relógio ... obrigado!
`` #
39

Para uma maneira rápida de ver o primeiro erro sem adicionar um relógio, você pode colá-lo na Janela Imediata:

((System.Data.Entity.Validation.DbEntityValidationException)$exception)
    .EntityValidationErrors.First()
    .ValidationErrors.First()
djdmbrwsk
fonte
1
Você também pode usar $ exception.EntityValidationErrors.SelectMany (x => x.ValidationErrors) .Select (x => x.ErrorMessage) para obter todos eles :) imho usando a janela imediata é a melhor resposta
chrispepper1989
15

Para quem trabalha em 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
fonte
12

Enquanto você estiver no modo de depuração dentro do catch {...}bloco, abra a janela "QuickWatch" ( ctrl+ alt+ q) e cole nela:

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

ou:

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

Se você não estiver em uma tentativa / captura ou não tiver acesso ao objeto de exceção.

Isso permitirá que você faça drill down na ValidationErrorsárvore. É a maneira mais fácil que eu encontrei de obter informações instantâneas sobre esses erros.

GONeale
fonte
10

Se você está simplesmente capturando uma exceção genérica, pode ser útil convertê- la como DbEntityValidationException . Esse tipo de exceção possui uma propriedade Erros de validação e, continuando a se expandir para eles, você encontrará todos os problemas.

Por exemplo, se você colocar um ponto de interrupção na captura, poderá lançar o seguinte em um relógio:

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

Um exemplo de erro é que, se um campo não permitir nulos, e você tiver uma sequência nula, verá que o campo é obrigatório.

Greg
fonte
9

basta verificar o comprimento do campo da tabela do banco de dados. Seu texto de entrada é maior que o comprimento do tipo de dados do campo da coluna

Hardeep Singh
fonte
9

Na depuração, você pode inserir isso no campo de entrada do avaliador de expressão do QuickWatch:

context.GetValidationErrors()
silverfox1948
fonte
8

A resposta do @Slauma é realmente ótima, mas achei que não funcionava quando uma propriedade ComplexType era inválida.

Por exemplo, digamos que você tenha uma propriedade Phonedo tipo complexo PhoneNumber. Se a AreaCodepropriedade for inválida, o nome da propriedade ve.PropertyNamesserá "Phone.AreaCode". Isso faz com que a chamada eve.Entry.CurrentValues<object>(ve.PropertyName)falhe.

Para corrigir isso, você pode dividir o nome da propriedade em cada um .e recursar pela matriz resultante de nomes de propriedades. Finalmente, quando você chega ao final da cadeia, pode simplesmente retornar o valor da propriedade.

Abaixo está a FormattedDbEntityValidationExceptionclasse de @ Slauma com suporte para ComplexTypes.

Aproveitar!

[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
fonte
1
Não posso acreditar que mais pessoas não tenham votado neste voto, pois é um cenário muito real e isso me deixou louco nas últimas duas noites. Você sabe que a sensação que você sente quando percebe que o tratamento de erros é o que realmente está causando o erro? Ugh.
DJ Grossman
7

Observe que Entity.GetType().BaseType.Namefornece o nome do tipo que você especificou, não aquele com todos os dígitos hexadecimais em seu nome.

Eric Nelson
fonte
7

De acordo com a resposta de @ Slauma e a sugestão de @ Milton, estendi o método de salvamento personalizado da classe base com uma tentativa / captura que tratará (e, portanto, registrará nosso log de erros!) Desse tipo de exceção.

// 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
fonte
1
Você pode usar sb.AppendFormat () diretamente
Bastien Vandamme
1
Você precisará adicionar sua própria nova linha também se usar AppendFormat.
jocull
7

Eu tive que escrever isso na janela Imediata: 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 se aprofundar no erro exato!

Nour Sabouny
fonte
6

Usando a resposta de @Slauma, criei um snippet de código (um rodeia com snippet) para melhor 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
fonte
5

Capture a exceção em uma tentativa de captura e, em seguida, observe rapidamente ou ctrl + d & ctrl + q e você pode detalhar os EntityValidationErrors.

Brandon.Staley
fonte
5

Apenas jogando meus dois centavos em ...

Dentro do meu dbConfiguration.cs, eu gosto de agrupar meu método context.SaveChanges () em uma tentativa / captura e produzir um arquivo de texto de saída que me permita ler os Erros claramente, e esse código também os timestamps - útil se você encontre mais de um erro em momentos diferentes!

        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;
        }
IfElseTryCatch
fonte
5

O que eu encontrei ... quando recebi o erro 'EntityValidationErrors' é que ... eu tenho um campo no meu banco de dados 'db1' na tabela 'tbladdress' como 'address1' com tamanho de 100 (ou seja, endereço varchar (100) null) e eu estava passando o valor com mais de 100 caracteres ... e isso levou a erros ao salvar os dados no banco de dados ....

Portanto, você deve verificar os dados que está passando para o campo.

Dharmendra Prajapati
fonte
1
Agradeço esta resposta porque ela realmente me ajudou a resolver meu erro. A tabela em que eu estava salvando no meu banco de dados tinha todas as not nullcolunas; assim, quando adicionei dados a todos os elementos anteriores ao meu, db.SaveChanges()não recebi nenhum erro.
BinaryJoe01
3

Isso funciona para mim.

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

Coloque um ponto de interrupção na instrução if. Então você pode verificar o modelState nas janelas de depuração. Em todo valor, você pode ver se há um erro e até a mensagem de erro. É isso aí. Quando você não precisar mais, basta excluir ou comentar a linha.

Espero que isso ajude.

Se solicitado, posso fornecer uma captura de tela detalhada na janela de depuração.

AngelDown
fonte
3

Como mencionado em outras postagens, simplesmente pegue a exceção na classe DbEntityValidationException. O que fornecerá o que você precisa durante os casos de erro.

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

Eu enfrentei esse erro antes

quando tentei atualizar um campo específico no meu modelo no framwork de entidade

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

e de acordo com as respostas acima

Encontrei a mensagem de validação The SignerName field is required.

qual apontando para o campo no meu modelo

e quando eu chequei meu esquema de banco de dados eu encontrei

insira a descrição da imagem aqui

tão fora coure ValidationException tem o direito de aumentar

e de acordo com esse campo, eu quero que seja anulável (não sei como estraguei tudo)

então mudei esse campo para permitir Nulo e, com isso, meu código não me dará esse erro novamente

Talvez esse erro ocorra se você invalidar a integridade dos seus dados do seu banco de dados

Basheer AL-MOMANI
fonte
1
Se uma exceção deve ou não ser levantada não é o ponto aqui. Em seguida, você está cortando alguns cantos aqui. Quando um campo é obrigatório no esquema do banco de dados, você precisa mais do que isso para gerar um DbEntityValidationException.
Gert Arnold
2

Por favor, verifique o valor dos campos que você está passando, são válidos e de acordo com os campos do banco de dados. Por exemplo, o número de caracteres passados ​​em um campo específico é menor que os caracteres definidos no campo da tabela do banco de dados.

arun tiwari
fonte
1

Se você estiver usando o IIS com autenticação do Windows e Entity Framework , tenha cuidado authorize.

Tentei POSTsem autorizar e não funcionou, e obter este erro no db.SaveChangesAsync();, enquanto todos os outros verbos GETe DELETEestavam trabalhando.

Mas quando adicionei AuthorizeAttribute como anotação, funcionou.

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

Aqui está outra maneira de fazer isso, em vez de usar loops foreach para procurar dentro de EntityValidationErrors. Obviamente, você pode formatar a mensagem como preferir:

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
fonte
1

No meu caso, foi por causa do comprimento do campo do banco de dados ser menor que o comprimento do campo de entrada.

tabela de banco de dados

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

Minha entrada

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

o valor de Username lengthé 5, que é lessthan6

... isso pode ajudar alguém

Qwerty
fonte
0

Verifique se você tem Not Nullrestrição nas colunas da tabela e não passa o valor para essa coluna durante as operações de inserção / atualização. Isso causa essa exceção na estrutura da entidade.

s Jagathish
fonte
0

Eu também enfrentei o mesmo problema. Atualizei meu .edmx do banco de dados depois que a exceção desapareceu.

HariChintha
fonte
0

Este erro ocorre principalmente devido ao tamanho do campo. VERIFIQUE todos os tamanhos de campo em uma tabela de banco de dados.

Alexander Zaldostanov
fonte
0

Também estava lutando com esse erro e com base no tópico aqui, e esta resposta foi capaz de descobrir um trecho para copiar / colar sem a necessidade de descobrir o que deve ser importado (excelente para iniciantes em C #), código abaixo:

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
fonte