Validasi gagal untuk satu entitas atau lebih. Lihat properti 'EntityValidationErrors' untuk detail lebih lanjut


804

Saya mengalami kesalahan ini saat menyemai database saya dengan pendekatan kode pertama.

Validasi gagal untuk satu entitas atau lebih. Lihat properti 'EntityValidationErrors' untuk detail lebih lanjut.

Sejujurnya saya tidak tahu bagaimana memeriksa konten kesalahan validasi. Visual Studio menunjukkan kepada saya bahwa itu adalah array dengan 8 objek, jadi 8 kesalahan validasi.

Ini bekerja dengan model saya sebelumnya, tetapi saya membuat beberapa perubahan yang saya jelaskan di bawah:

  • Saya memiliki enum bernama Status, saya mengubahnya ke kelas yang disebut Status
  • Saya mengubah kelas ApplicantsPositionHistory untuk memiliki 2 kunci asing ke tabel yang sama

Maafkan saya untuk kode yang panjang, tapi saya harus menempel semuanya. Pengecualian dilemparkan di baris terakhir dari kode berikut.

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

Jawaban:


1237

Sejujurnya saya tidak tahu bagaimana memeriksa konten kesalahan validasi. Visual Studio menunjukkan kepada saya bahwa itu adalah array dengan 8 objek, jadi 8 kesalahan validasi.

Sebenarnya Anda akan melihat kesalahan jika Anda menelusuri array di Visual studio selama debug. Tetapi Anda juga dapat menangkap pengecualian dan kemudian menulis kesalahan ke beberapa toko logging atau konsol:

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

EntityValidationErrorsadalah koleksi yang mewakili entitas yang tidak dapat divalidasi dengan sukses, dan koleksi dalam ValidationErrorsper entitas adalah daftar kesalahan pada tingkat properti.

Pesan validasi ini biasanya cukup membantu untuk menemukan sumber masalahnya.

Edit

Beberapa perbaikan kecil:

The nilai dari properti menyinggung dapat dimasukkan dalam loop batin seperti:

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

Walaupun debugging Debug.Writemungkin lebih disukai Console.WriteLinekarena dapat digunakan di semua jenis aplikasi, tidak hanya aplikasi konsol (terima kasih kepada @Bart untuk catatannya di komentar di bawah).

Untuk aplikasi web yang sedang dalam produksi dan yang menggunakan Elmah untuk penebangan pengecualian, ternyata sangat berguna bagi saya untuk membuat pengecualian khusus dan menimpa SaveChangesuntuk membuang pengecualian baru ini.

Jenis pengecualian khusus terlihat seperti ini:

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

Dan SaveChangesdapat ditimpa dengan cara berikut:

public class MyContext : DbContext
{
    // ...

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

Beberapa komentar:

  • Layar kesalahan kuning yang ditampilkan Elmah di antarmuka web atau email yang terkirim (jika Anda sudah mengonfigurasinya) sekarang menampilkan detail validasi langsung di bagian atas pesan.

  • Menimpa Messageproperti dalam pengecualian khusus alih-alih menimpa ToString()memiliki manfaat bahwa ASP.NET standar "Layar kuning kematian (YSOD)" juga menampilkan pesan ini. Berbeda dengan Elmah, YSOD tampaknya tidak digunakan ToString(), tetapi keduanya menampilkan Messageproperti.

  • Membungkus dokumen asli DbEntityValidationExceptionsebagai pengecualian dalam memastikan bahwa jejak tumpukan asli masih akan tersedia dan ditampilkan dalam Elmah dan YSOD.

  • Dengan menetapkan breakpoint di telepon, throw newException;Anda cukup memeriksa newException.Messageproperti sebagai teks alih-alih menelusuri koleksi validasi yang agak canggung dan tampaknya tidak bekerja dengan mudah untuk semua orang (lihat komentar di bawah).


87
Mengebor pengecualian tidak melakukan apa-apa. Itu hanya mengatakan ada DbEntityValidationResult tetapi tidak membiarkan Anda berkembang !!
Shumii

30
@ Shumii Lihat jawaban ini untuk memperluas pengecualian.
Cavyn VonDeylen

18
Hanya untuk memperluas solusi yang elegan. Anda mungkin ingin mengganti metode savechanges di kelas DbContext Anda sendiri, dan kemudian menambahkan blok try catch, di mana blok try hanya mencoba untuk menyimpan (base.SaveChanges ()), dan blok catch hanya menangkap DbEntityValidationException. Dengan cara ini, Anda tidak perlu menambahkannya di setiap tempat Anda menyimpan perubahan.
Milton

7
Ini telah menghemat bacon saya lebih dari satu kali. Saya hanya bisa memilih satu kali. Berharap mereka membiarkan saya menang untuk setiap kali saya menyalin dan menempel ini.
Damon Drake

5
+2 untuk kode. Memang penyelamat :) -1 untuk menggunakan Console.WriteLine, saya memperkirakan lebih banyak orang menulis proyek web kemudian menghibur aplikasi saat ini, dan Debug.Writebekerja di keduanya ...
Bart

459

Anda dapat melakukannya dari Visual Studio selama debugging tanpa menulis kode apa pun, bahkan tidak menangkap blok.

Cukup tambahkan arloji dengan nama:

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

Ekspresi arloji $exceptionmenampilkan pengecualian yang dilemparkan dalam konteks saat ini, bahkan jika itu belum ditangkap dan ditugaskan ke variabel.

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


39
+1 Solusi yang lebih baik, dan tidak memerlukan perubahan kode. Keren
Justas

4
+1 ini sangat, sangat berguna! Anda bahkan tidak perlu memiliki blok coba / tangkap. Cukup taruh ini di daftar pantauan ketika VS istirahat dan voila .. Anda punya kesalahan validasi di depan Anda.
theyetiman

40
beberapa kali setahun saya lupa bagaimana melakukan ini dan menemukan jawaban ini
Justin Moore

3
@ zairja Saya belum mengujinya di vb.net, tetapi tampaknya variabel tersebut didefinisikan untuk vb.net juga di msdn.microsoft.com/en-us/library/ms164891.aspx , namun para pemerannya mungkin tidak didefinisikan untuk vb.net, dan sebagai gantinya Anda mungkin harus melakukan DirectCast ($ exception, System.Data.Entity.Validation.DbEntityValidationException)
yoel halb

2
Saya tahu bahwa "terima kasih" tidak diterima dalam komentar tetapi demi mencegah saya menghabiskan waktu berjam-jam ... terima kasih!
Luther

105

Ini sebenarnya dapat melakukannya tanpa harus menulis kode:

Di blok tangkap Anda, tambahkan break point di baris kode berikut:

catch (Exception exception)
{

}

Sekarang jika Anda mengarahkan exceptionatau menambahkannya ke Watchdan kemudian masuk ke detail pengecualian seperti yang ditunjukkan di bawah ini; Anda akan melihat kolom mana yang menyebabkan masalah karena kesalahan ini biasanya terjadi ketika kendala tabel dilanggar ..

masukkan deskripsi gambar di sini

Gambar besar


4
Pendekatan ini sangat sederhana dan memanfaatkan IDE :)
dsnunez

3
Ini adalah solusi yang baik karena cepat, sederhana, memanfaatkan IDE, dan menyelamatkan saya banyak waktu.
maxshuty

2
Saya suka dengan cara ini "Bagaimana menjadi seorang koder dan tidak melakukan kode"
buka dan gratis

1
Terima kasih. Ini sederhana tetapi mengagumkan melihat pengecualian menggunakan IDE.
Thomas.Benz

solusi sempurna
Neeraj Singh Chouhan

46

Inilah cara Anda dapat memeriksa konten EntityValidationErrors di Visual Studio (tanpa menulis kode tambahan) yaitu selama Debugging di IDE .

Masalah?

Anda benar, Popup debugger Visual Studio Lihat Detail tidak menunjukkan kesalahan aktual di dalam EntityValidationErrorskoleksi.

masukkan deskripsi gambar di sini

Solusinya!

Cukup tambahkan ekspresi berikut di jendela Quick Watch dan klik Reevaluate .

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

Dalam kasus saya, lihat bagaimana saya dapat memperluas ke bagian ValidationErrors Listdalam EntityValidationErrorskoleksi

masukkan deskripsi gambar di sini

: Referensi mattrandle.me posting blog , jawaban @ Yoel ini


3
mengapa ini belum diperbaiki? itu seharusnya menunjukkan kesalahan bukan sesuatu yang lain
Geomorillo

2
Kesalahan validasi menunjukkan kesalahan properti, mis. bidang subjek diperlukan, jawaban yang baik, Terima kasih
hamzeh.hanandeh

1
Bagus! Itu menyelamatkan malam saya! :)
Patrick

1
ini adalah cara cerdas untuk memvisualisasikan kesalahan yang tepat di jam tangan ... terima kasih!
Qwerty

39

Untuk cara cepat melihat kesalahan pertama tanpa menambahkan arloji Anda dapat menempel ini di Jendela Segera:

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

1
Anda juga dapat menggunakan $ exception.EntityValidationErrors.SelectMany (x => x.ValidationErrors) .Pilih (x => x.ErrorMessage) untuk mendapatkan semuanya :) :) menggunakan jendela langsung adalah jawaban terbaik
chrispepper1989

15

Bagi siapa saja yang bekerja di 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

Saat Anda dalam mode debug di dalam catch {...}blok, buka jendela "QuickWatch" ( ctrl+ alt+ q) dan tempel di sana:

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

atau:

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

Jika Anda tidak mencoba / menangkap atau tidak memiliki akses ke objek pengecualian.

Ini akan memungkinkan Anda untuk menelusuri ValidationErrorspohon. Ini cara termudah yang saya temukan untuk mendapatkan wawasan instan tentang kesalahan ini.


10

Jika Anda hanya menangkap pengecualian umum, mungkin bermanfaat bagi Anda untuk melemparkan ini sebagai DbEntityValidationException . Jenis pengecualian ini memiliki properti Kesalahan Validasi, dan terus memperluas jalan ke dalamnya, Anda akan menemukan semua masalah.

Misalnya, jika Anda memasukkan break point ke dalam tangkapan, Anda bisa melempar yang berikut ke arloji:

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

Contoh kesalahan adalah jika bidang tidak mengizinkan nol, dan Anda memiliki string nol, Anda akan melihatnya mengatakan bahwa bidang tersebut wajib diisi.


9

cukup Periksa Panjang Tabel Tabel Database Anda. Teks Input Anda Lebih Besar dari panjang jenis data kolom bidang


9

Dalam debug, Anda bisa memasukkan ini di bidang entri evaluator ekspresi QuickWatch Anda:

context.GetValidationErrors()

8

Jawaban dari @Slauma benar-benar hebat tetapi saya menemukan bahwa itu tidak berfungsi ketika properti ComplexType tidak valid.

Misalnya, Anda memiliki properti Phonetipe kompleks PhoneNumber. Jika AreaCodeproperti tidak valid, nama properti di ve.PropertyNamesadalah "Phone.AreaCode". Ini menyebabkan panggilan eve.Entry.CurrentValues<object>(ve.PropertyName)gagal.

Untuk memperbaiki ini, Anda dapat membagi nama properti di masing-masing . , lalu mengulangi melalui array yang dihasilkan dari nama properti. Akhirnya, ketika Anda tiba di bagian bawah rantai, Anda cukup mengembalikan nilai properti.

Di bawah ini adalah @ Slauma FormattedDbEntityValidationException kelas dengan dukungan untuk ComplexTypes.

Nikmati!

[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
Saya tidak percaya lebih banyak orang yang tidak memilih ini, karena ini adalah skenario yang sangat nyata dan telah membuat saya gila selama dua malam terakhir. Anda tahu bahwa perasaan yang Anda dapatkan ketika Anda menyadari penanganan kesalahan Anda adalah apa yang sebenarnya menyebabkan kesalahan? Ugh.
DJ Grossman

7

Catatan yang Entity.GetType().BaseType.Namememberikan nama tipe yang Anda tentukan, bukan yang memiliki semua digit hex dalam namanya.


7

Jawaban Per @ Slauma dan saran @ Milton Saya telah memperpanjang metode penyimpanan kustom kelas dasar kami dengan try / catch yang akan menangani (dan karenanya login kesalahan log kami!) Semacam pengecualian ini.

// 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
Anda dapat menggunakan sb.AppendFormat () secara langsung
Bastien Vandamme

1
Anda juga perlu menambahkan baris baru Anda sendiri jika menggunakan AppendFormat.
jocull

7

Saya harus menulis ini di jendela Segera: 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]

untuk mengetahui kesalahan yang sebenarnya!


6

Menggunakan jawaban @Slauma saya telah membuat potongan kode (surround dengan potongan) untuk penggunaan yang lebih baik.

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

Tangkap pengecualian dalam try catch dan kemudian tonton cepat atau ctrl + d & ctrl + q dan Anda dapat menelusuri EntityValidationErrors.


5

Hanya melempar dua sen saya ke ...

Dalam dbConfiguration.cs saya, saya ingin membungkus metode context.SaveChanges () saya menjadi try / catch dan menghasilkan file teks keluaran yang memungkinkan saya untuk membaca Kesalahan dengan jelas, dan kode ini juga mencatat waktu mereka - berguna jika Anda mengalami lebih dari satu kesalahan pada waktu yang berbeda!

        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

Apa yang saya temukan ... ketika saya mendapatkan kesalahan 'EntityValidationErrors' adalah bahwa .... saya memiliki bidang dalam database saya 'db1' dalam tabel 'tbladdress' sebagai 'address1' yang memiliki ukuran 100 (yaitu alamat varchar (100) null) dan saya memberikan nilai lebih dari 100 karakter..dan ini menyebabkan kesalahan saat menyimpan data ke basis data ....

Jadi, Anda harus Periksa data yang Anda berikan ke bidang.


1
Saya menghargai jawaban ini karena sebenarnya membantu saya menyelesaikan kesalahan saya. Tabel yang saya simpan di db saya memiliki semua not nullkolom jadi setelah saya menambahkan data ke semua elemen sebelum saya db.SaveChanges()saya tidak menerima kesalahan.
BinaryJoe01

3

Ini bekerja untuk saya.

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

Beri breakpoint pada pernyataan if. Kemudian Anda dapat memeriksa modelState di jendela debug. Pada setiap nilai Anda dapat melihat apakah ada kesalahan dan bahkan pesan kesalahan. Itu dia. Ketika Anda tidak membutuhkannya lagi, cukup hapus atau komentari baris tersebut.

Saya harap ini akan membantu.

Jika ditanya, saya dapat memberikan tangkapan layar terperinci di jendela debug.


3

Seperti disebutkan dalam posting lain, cukup tangkap pengecualian di kelas DbEntityValidationException. Yang akan memberi Anda apa pun yang Anda butuhkan selama kasus kesalahan.

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

2

Saya menghadapi kesalahan ini sebelumnya

ketika saya mencoba untuk memperbarui bidang tertentu dalam model saya dalam bingkai entitas

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

dan menurut jawaban di atas

Saya menemukan pesan Validasi The SignerName field is required.

yang menunjuk ke bidang dalam model saya

dan ketika saya memeriksa skema database saya, saya menemukan

masukkan deskripsi gambar di sini

jadi off coure ValidationExceptionmemiliki hak untuk menaikkan

dan menurut bidang ini saya ingin nullable, (Saya tidak tahu bagaimana saya mengacaukannya)

jadi saya mengubah bidang itu untuk memungkinkan Null, dan dengan ini kode saya tidak akan memberi saya kesalahan ini lagi

jadi kesalahan ini mungkin akan terjadi jika Anda membatalkan integritas data Anda dari database Anda


1
Apakah pengecualian harus diajukan atau tidak bukan intinya di sini. Selanjutnya, Anda memotong beberapa sudut di sini. Ketika suatu bidang diperlukan dalam skema basis data, Anda perlu lebih dari itu untuk DbEntityValidationExceptionmengangkat.
Gert Arnold

2

Silakan periksa nilai bidang yang Anda lewati, apakah valid dan sesuai dengan bidang basis data. Misalnya jumlah karakter yang diteruskan dalam bidang tertentu kurang dari karakter yang ditentukan dalam bidang tabel database.


1

Jika Anda menggunakan IIS dengan Windows Authentication and Entity Framework , berhati-hatilah untuk menggunakannyaauthorize .

Saya mencoba POSTtanpa otorisasi dan itu tidak berhasil, dan mendapatkan kesalahan ini db.SaveChangesAsync();, sementara semua kata kerja GETdan lainnyaDELETE sedang bekerja.

Tetapi ketika saya menambahkan AuthorizeAttribute sebagai anotasi, itu berhasil.

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

1

Berikut cara lain untuk melakukannya daripada menggunakan foreach loop untuk mencari di dalam EntityValidationErrors. Tentu saja Anda dapat memformat pesan sesuai keinginan Anda:

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

Dalam kasus saya itu karena panjang bidang basis data kurang dari panjang bidang masukan.

tabel basis data

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

Masukan saya

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

nilai untuk Username lengthadalah 5 yanglessthan 6

... ini dapat membantu seseorang


0

Periksa apakah Anda memiliki Not Nullkendala dalam kolom tabel Anda dan Anda tidak melewati nilai untuk kolom itu saat memasukkan / Perbarui operasi. Itu menyebabkan pengecualian ini dalam kerangka entitas.


0

Saya juga menghadapi masalah yang sama. Saya memperbarui .edmx saya dari database setelah itu pengecualian telah hilang.



0

Juga berjuang dengan kesalahan ini dan berdasarkan pada topik di sini dan jawaban ini dapat menemukan potongan untuk menyalin / menempel tanpa perlu mencari tahu apa yang harus diimpor (sangat baik untuk pemula C #), kode di bawah ini:

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);
    }
  }
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.