Bir veya daha fazla varlık için doğrulama başarısız oldu. Daha fazla ayrıntı için 'EntityValidationErrors' özelliğine bakın


804

Kod ilk yaklaşım ile benim veritabanı tohumlama sırasında bu hatayı alıyorum.

Bir veya daha fazla varlık için doğrulama başarısız oldu. Daha fazla ayrıntı için 'EntityValidationErrors' özelliğine bakın.

Dürüst olmak gerekirse, doğrulama hatalarının içeriğini nasıl kontrol edeceğimi bilmiyorum. Visual Studio, 8 nesne içeren bir dizi olduğunu gösterir, bu nedenle 8 doğrulama hatası.

Bu önceki modelimle çalışıyordu, ancak aşağıda açıkladığım birkaç değişiklik yaptım:

  • Status adlı bir numaralandırma kullandım, Status adlı bir sınıfa değiştirdim
  • ApplicantsPositionHistory sınıfını aynı tabloda 2 yabancı anahtar olacak şekilde değiştirdim

Uzun kod için özür dilerim, ama hepsini yapıştırmam gerekiyor. İstisna, aşağıdaki kodun son satırına atılır.

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

Yanıtlar:


1237

Dürüst olmak gerekirse, doğrulama hatalarının içeriğini nasıl kontrol edeceğimi bilmiyorum. Visual Studio, 8 nesne içeren bir dizi olduğunu gösterir, bu nedenle 8 doğrulama hatası.

Aslında, hata ayıklama sırasında Visual Studio'da bu diziye detaya girerseniz hataları görmelisiniz. Ancak, istisnayı yakalayabilir ve daha sonra hataları bazı günlük deposuna veya konsola yazabilirsiniz:

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 başarıyla doğrulanamayan varlıkları temsil eden bir koleksiyon ve iç koleksiyon ValidationErrors varlık başına , mülk düzeyindeki hataların bir listesidir.

Bu doğrulama iletileri genellikle sorunun kaynağını bulabilecek kadar yardımcı olur.

Düzenle

Birkaç küçük iyileştirme:

Sorun yaratan özelliğin değeri iç döngüye şu şekilde dahil edilebilir:

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

Hata ayıklama , yalnızca konsol uygulamalarında değil, her türlü uygulamada çalıştığı Debug.Writeiçin tercih Console.WriteLineedilebilir (aşağıdaki yorumlarda notu için @Bart'a teşekkürler).

Üretimde olan ve istisna günlüğü için Elmah kullanan web uygulamaları için, özel bir istisna oluşturmamın ve SaveChangesbu yeni istisnayı atmak için üzerine yazmamın çok yararlı olduğu ortaya çıktı .

Özel istisna türü şuna benzer:

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

Ve SaveChangesaşağıdaki şekilde üzerine yazılabilir:

public class MyContext : DbContext
{
    // ...

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

Birkaç açıklama:

  • Elmah'ın web arayüzünde veya gönderilen e-postalarda (bunu yapılandırdıysanız) gösterilen sarı hata ekranı artık doğrulama ayrıntılarını doğrudan mesajın üstünde görüntüler.

  • Üzerine yazmak MessageÜzerine yazmak yerine özel istisna tesise ToString()faydası standart ASP.NET "ölüm (YSOD) Sarı ekran" görüntüler bu mesajla etmiştir. Elmah'ın aksine YSOD görünüşte kullanmıyor ToString(), ancak her ikisi de Messageözelliği gösteriyor.

  • Orijinalin DbEntityValidationExceptioniç istisna olarak sarılması, orijinal yığın izinin hala kullanılabilir olmasını sağlar ve Elmah ve YSOD'da görüntülenir.

  • Hatta bir kesme noktası ayarlayarak , biraz garip olan ve herkes için kolay çalışmayan doğrulama koleksiyonlarına girmek yerine özelliği bir metin olarak throw newException;inceleyebilirsiniz newException.Message(aşağıdaki yorumlara bakın).


87
İstisnaya girmek hiçbir şey yapmaz. Sadece bir DbEntityValidationResult olduğunu söylüyor ama genişletmenize izin vermiyor !!
Shumii

30
@Shumii İstisnayı genişletmek için bu cevaba bakınız .
Cavyn VonDeylen

18
Sadece zarif bir çözümü genişletmek için. Kendi DbContext sınıfınızdaki savechanges yöntemini geçersiz kılmak ve sonra try bloğunun kaydetmeye çalıştığı (base.SaveChanges ()) ve catch bloğunun yalnızca DbEntityValidationException yakaladığı try catch bloğunu ekleyebilirsiniz. Bu şekilde, değişikliklerinizi kaydettiğiniz her yere eklemenize gerek yoktur.
Milton

7
Bu, pastırmamı birden fazla vesileyle kurtardı. Sadece bir kere vekalet edebilirim. Bunu her kopyalayıp yapıştırdığımda izin vermelerini isterdim.
Damon Drake

5
Kod için +2. Gerçekten bir kurtarıcı :) -1 kullanmak için Console.WriteLine, tahmin ediyorum daha fazla insan web projeleri yazıyor sonra konsol uygulamaları bugünlerde, ve Debug.Writeher ikisi de çalışır ...
Bart

459

Hata ayıklama sırasında herhangi bir kod yazmadan, hatta bir catch bloğu bile değil, Visual Studio'dan yapabilirsiniz.

Sadece şu isimle bir saat ekleyin:

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

Watch ifadesi $exception, yakalanmamış ve bir değişkene atanmamış olsa bile geçerli bağlamda atılan istisnaları görüntüler.

Göre http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/


39
+1 Way daha iyi bir çözümdür ve kodda değişiklik gerektirmez. Cool
Justas

4
+1 bu çok, çok kullanışlı! Bir try / catch bloğuna bile ihtiyacınız yok. Sadece VS mola ve voila zaman izleme listesine sopa .. önünüzde doğrulama hataları var.
theyetiman

40
yılda birkaç kez Bunu yapmayı ve bu cevabı nasıl bulacağımı unuttum
Justin Moore

3
@zairja vb.net'te test etmedim, ancak değişkenin vb.net için de msdn.microsoft.com/en-us/library/ms164891.aspx'de tanımlandığı anlaşılıyor , ancak döküm muhtemelen değil vb.net için tanımlanmış ve bunun yerine muhtemelen DirectCast ($ exception, System.Data.Entity.Validation.DbEntityValidationException)
yoel halb

2
Ben "teşekkürler" yorumlarda hoş değil ama bana boşa zaman saatler önleme uğruna olduğunu biliyorum ... teşekkürler!
Luther

105

Bu aslında kod yazmak zorunda kalmadan yapabilirdi:

Yakalama bloğunuza, aşağıdaki kod satırına bir kesme noktası ekleyin:

catch (Exception exception)
{

}

Şimdi üzerine geldiyseniz exceptionveya üzerine eklerseniz Watchve aşağıda gösterildiği gibi istisna ayrıntılarına giderseniz ; bu hata genellikle bir tablo kısıtlaması ihlal edildiğinde oluştuğu için hangi belirli sütunların soruna neden olduğunu göreceksiniz.

resim açıklamasını buraya girin

Büyük resim


4
Bu yaklaşım çok basit ve IDE'den yararlanıyor :)
dsnunez

3
Bu iyi bir çözüm çünkü hızlı, basit, IDE'yi kullanıyor ve beni tonlarca zamandan kurtardı.
maxshuty

2
Ben bu şekilde "Nasıl kodlayıcı olmak ve kod yapmak için değil"
açık ve ücretsiz

1
Teşekkür ederim. Bu basit ama IDE kullanarak istisnayı görmek harika.
Thomas.Benz

mükemmel çözüm
Neeraj Singh Chouhan

46

Burada içeriğini şekilde kontrol edebilirsiniz EntityValidationErrors sırasında yani (fazladan kod yazmadan) Visual Studio Debugging'ı içinde IDE .

Sorun?

Haklısınız, Visual Studio hata ayıklayıcısının Ayrıntıları Görüntüle Açılır Penceresi EntityValidationErrorskoleksiyondaki gerçek hataları göstermiyor .

resim açıklamasını buraya girin

Çözüm!

Aşağıdaki ifadeyi bir Hızlı İzleme penceresine ekleyin ve Yeniden Değerlendir'i tıklayın .

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

Benim durumumda, ben uzanabilmekten ne kadar bakın ValidationErrors Listiçeride EntityValidationErrorskoleksiyon

resim açıklamasını buraya girin

Kaynaklar: mattrandle.me blog yazısı , @ yoel'in cevabı


3
bu neden düzeltilmedi? hatayı başka bir şey değil göstermelidir
Geomorillo

2
Doğrulama hatası, özellik hatasını gösterir, örn. konu alanı zorunlu, iyi yanıt, Teşekkür ederim
hamzeh.hanandeh

1
Harika! Gecemi kurtardı! :)
Patrick

1
Bu, saatteki kesin hatayı görselleştirmenin akıllı bir yoludur ... teşekkür ederim!
Qwerty

39

Saat eklemeden bile ilk hatayı görmenin hızlı bir yolu için bunu Anlık Pencereye yapıştırabilirsiniz:

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

1
Ayrıca $ exception.EntityValidationErrors.SelectMany (x => x.ValidationErrors) öğesini de kullanabilirsiniz. Hepsini almak için (x => x.ErrorMessage) öğesini seçin :) imho, anlık pencereyi kullanarak en iyi cevaptır
chrispepper1989

15

Çalışan herkes için 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

12

catch {...}Blok içinde hata ayıklama modundayken "QuickWatch" penceresini ( ctrl+ alt+ q) açın ve buraya yapıştırın:

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

veya:

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

Bir try / catch uygulamasında değilseniz veya istisna nesnesine erişiminiz yoksa.

Bu, ValidationErrorsağaca detaya inmenizi sağlayacaktır . Bu hataları anında anlamanın en kolay yolu.


10

Sadece genel bir istisna yakalıyorsanız, bunu bir DbEntityValidationException olarak kullanmanız yarar sağlayabilir . Bu tür bir istisnanın bir Doğrulama Hataları özelliği vardır ve bunlara doğru yolunuzu genişletmeye devam ederek, tüm sorunları bulacaksınız.

Örneğin, yakalamaya bir kırılma noktası koyarsanız, aşağıdakileri bir saate atabilirsiniz:

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

Bir hata örneği, bir alanın null değerlere izin vermemesi ve null bir dizeniz varsa, bunun alanın gerekli olduğunu söyleyeceğini göreceksiniz.


9

Veritabanı Tablonuzun Alan Uzunluğunu Kontrol Edin. Giriş Metniniz sütun alanı veri türü uzunluğundan daha büyük


9

Hata ayıklamada, bunu QuickWatch ifade değerlendiricisi giriş alanına girebilirsiniz:

context.GetValidationErrors()

8

@Slauma cevap gerçekten harika ama bir ComplexType özelliği geçersiz olduğunda işe yaramadı bulundu.

Örneğin Phone, karmaşık türde bir özelliğiniz olduğunu varsayalım PhoneNumber. Eğer AreaCodemülkiyet geçersiz, mülkiyet adı ve.PropertyNames"Phone.AreaCode" dir. Bu, çağrının eve.Entry.CurrentValues<object>(ve.PropertyName)başarısız olmasına neden olur.

Bunu düzeltmek için, özellik adını her birine bölebilir .ve sonuçta elde edilen özellik adları dizisini tekrarlayabilirsiniz. Son olarak, zincirin altına geldiğinizde, mülkün değerini geri verebilirsiniz.

Aşağıda @ Slauma'nın FormattedDbEntityValidationExceptionComplexTypes destekli sınıfı bulunmaktadır.

Zevk almak!

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

1
Daha fazla insanın bunu reddetmediğine inanamıyorum, çünkü bu çok gerçek bir senaryo ve son iki gece beni deli ediyor. Hata işlemenin farkına vardığınızda aldığınız hissin, hatayı gerçekten atmanın ne olduğunu biliyor musunuz? Ugh.
DJ Grossman

7

Not Entity.GetType().BaseType.NameBelirtilen tür adı, adının tüm onaltılık basamak ile değil tane verir.


7

@ Slauma'nın yanıtı ve @ Milton'ın önerisi uyarınca, temel sınıfımızın özel kaydetme yöntemini, bu tür istisnaları ele alacak bir denemeye / yakalamaya genişlettik (ve bu nedenle hata günlüğümüze giriş yapın!).

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

1
Sb.AppendFormat () öğesini doğrudan kullanabilirsiniz
Bastien Vandamme

1
AppendFormat kullanıyorsanız, kendi yeni satırınızı da eklemeniz gerekir.
jocull

7

Bunu Anında pencereye yazmak zorunda kaldım: 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]

kesin hatayı derinlemesine almak için!


6

@Slauma cevabını kullanarak daha iyi kullanmak için bir kod snippet'i (snippet ile çevreleyen) yaptım.

<?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>

5

Deneme yakalamasında istisnayı yakalayın ve ardından hızlı izleyin veya ctrl + d & ctrl + q ve EntityValidationErrors öğesine gidebilirsiniz.


5

Sadece iki sentimi ...

Benim dbConfiguration.cs içinde, bağlamım.SaveChanges () yöntemimi bir try / catch içine sarmak ve Hata (lar) açıkça okumak için izin veren bir çıkış metin dosyası üretmek istiyorum ve bu kod da onları zaman damgaları - kullanışlı farklı zamanlarda birden fazla hataya rastlamak!

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

5

Ne buldum ... 'EntityValidationErrors' hatası var .... benim veritabanında 'db1' tablo 'tbladdress' 100 boyutu olan 'address1' olarak bir alan var (yani adres varchar (100) null) ve ben 100'den fazla karakter değer geçiriyordu ... ve bu veri veritabanına kaydederken hataya neden ....

Bu nedenle, alana ilettiğiniz verileri kontrol etmelisiniz.


1
Bu yanıtı takdir ediyorum çünkü aslında benim hatamı çözmeme yardımcı oldu. Benim db içinde kaydediyordu tablo tüm not nullsütunları vardı, bu yüzden önce tüm öğelere veri ekledikten sonra db.SaveChanges()hiçbir hata almadım.
BinaryJoe01

3

Bu benim için çalışıyor.

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

İf ifadesine bir kesme noktası koyun. Ardından hata ayıklama pencerelerinde modelState'i kontrol edebilirsiniz. Her değerde bir hata ve hatta hata mesajı olup olmadığını görebilirsiniz. Bu kadar. Artık ihtiyacınız olmadığında satırı silin veya yorum yapın.

Umarım bu yardımcı olacak.

Sorulursa, hata ayıklama penceresinde ayrıntılı ekran görüntüsü sağlayabilirim.


3

Diğer yazılarda belirtildiği gibi, sadece DbEntityValidationException sınıfındaki özel durumu yakalayın. Hangi hata durumlarda size gerekli watever verecektir.

 try
 {
  ....
 }
 catch(DbEntityValidationException ex)
 {
  ....
 }

2

Bu hatayla daha önce karşılaştım

varlık çerçevesindeki modelimdeki belirli bir alanı güncellemeye çalıştığımda

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

ve yukarıdaki cevaplara göre

Doğrulama mesajını buldum The SignerName field is required.

modelimdeki alana işaret eden

ve veritabanı şememi kontrol ettiğimde

resim açıklamasını buraya girin

öyleyse coure'un ValidationExceptionyükseltme hakkı vardır

ve bu alana göre boş bırakılmasını istiyorum (nasıl berbat ettiğimi bilmiyorum)

bu yüzden Null'a izin vermek için bu alanı değiştirdim ve bu sayede kodum bana bu hatayı bir daha vermeyecek

Bu nedenle, veritabanınızın Verilerinizin bütünlüğünü geçersiz kılarsanız bu hata gerçekleşebilir


1
İstisna gündeme getirilip getirilmeyeceği burada mesele değildir. Sonra, burada bazı köşeleri kesiyorsun. Veritabanı şemasında bir alan gerektiğinde, DbEntityValidationExceptionyükseltilmesi için bundan daha fazlasına ihtiyacınız vardır .
Gert Arnold

2

Lütfen geçmekte olduğunuz alanların değerini, geçerli ve veritabanı alanlarına göre kontrol edin. Örneğin, belirli bir alana iletilen karakter sayısı, veritabanı tablosu alanında tanımlanan karakterlerden daha az.


1

Eğer kullanıyorsanız IIS ile , Windows Authentification ve Entity Framework , kullanmaya dikkat authorize.

POSTYetkisiz olarak denedim ve işe yaramadı ve db.SaveChangesAsync();diğer tüm fiiller varken bu hatayı aldım GETve DELETEçalışıyorlardı.

Ancak açıklama olarak AuthorizeAttribute'ı eklediğimde işe yaradı.

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

1

EntityValidationErrors içine bakmak için foreach döngülerini kullanmak yerine bunu yapmanın başka bir yolu. Elbette mesajı kendi isteğinize göre biçimlendirebilirsiniz:

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

1

Benim durumumda veritabanı alanının uzunluğu giriş alanının uzunluğundan daha az olması nedeniyle oldu.

veritabanı tablosu

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

Girişim

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

değeri Username lengtholan 5 olan lessthan6

... bu birine yardımcı olabilir


0

Not NullTablo sütunlarınızda kısıtlama olup olmadığını ve ekleme / Güncelleme işlemleri sırasında bu sütun için değeri geçip geçmediğinizi kontrol edin . Varlık çerçevesinde bu istisnanın nedeni.


0

Aynı problemle de karşılaştım. İstisna ortadan kalktıktan sonra veritabanımdan .edmx güncelledim.


0

Bu hata çoğunlukla alan boyutu nedeniyle oluşur. Bir veritabanı tablosundaki tüm alan boyutlarını kontrol edin.


0

Ayrıca bu hatayla mücadele ediyordu ve buradaki konuya dayanıyordu ve bu cevap , nelerin içe aktarılması gerektiğini (C # yeni başlayanlar için mükemmel), aşağıdaki kodu anlamaya gerek kalmadan kopyalamak / yapıştırmak için snippet'i anlayabildi:

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);
    }
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.