Mendapatkan jenis kesalahan yang tepat dari DbValidationException

184

Saya memiliki situasi di mana saya menginisialisasi model saya di DatabaseInitializer () untuk EF 4.1 dan mendapatkan kesalahan yang mengganggu ini "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."Jadi, saya pergi ke EntityValidationErrors ini dan ada bidang {System.Data.Entity.Validation.DbEntityValidationResult}yang tidak memberi saya informasi sama sekali tentang bidang apa yang tidak dapat diinisialisasi. . Apakah ada cara untuk mendapatkan lebih banyak info tentang kesalahan ini?

Untuk membersihkan:

Saya tahu cara memperbaiki masalah panjang string. Yang saya tanyakan adalah bagaimana cara mendapatkan nama bidang yang tepat yang melanggar model.

Naz
sumber

Jawaban:

377

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

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

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

Untuk pengguna Visual 2012+ yang hanya peduli tentang kesalahan pertama dan mungkin tidak memiliki catchblok, Anda bahkan dapat melakukan:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage
GONeale
sumber
9
Ini lebih baik daripada jawaban yang lain :)
Doug
98
Jika Anda tidak memiliki catch catch, Anda dapat menggantinya exdengan $exceptiondan mendapatkan hasil yang sama.
Ecyrb
juga pastikan Anda mengganti exdengan w / e Anda catch (Exception THIS)adalah
Eonasdan
@Ecyrb, terima kasih. Anda menyimpan jam Googling. Juga, bahkan jika jumlah kesalahan validasi ditunjukkan sebagai 1, sebenarnya ada dua elemen dalam array dengan dua kesalahan.
matrix
3
Bagi yang tidak mereferensikan System.Linq dan menggunakan jendela langsung:System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage
jpsimard-nyx
124

Anda dapat mencoba ini di blok coba / tangkap?

catch (DbEntityValidationException dbEx)
{
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
        foreach (var validationError in validationErrors.ValidationErrors)
        {
            Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage);
        }
    }
}
Trent Scholl
sumber
11

Solusi terbaik menurut saya, adalah menangani kesalahan semacam ini secara terpusat.

cukup tambahkan metode ini ke DbContextkelas utama :

public override int SaveChanges()
{
    try
    {
        return base.SaveChanges();
    }
    catch (DbEntityValidationException ex)
    {
        string errorMessages = string.Join("; ", ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.PropertyName + ": " + x.ErrorMessage));
        throw new DbEntityValidationException(errorMessages);
    }
}

Ini akan menimpa SaveChanges()metode konteks Anda dan Anda akan mendapatkan daftar yang dipisahkan koma yang berisi semua kesalahan validasi entitas.

Semoga ini bermanfaat.

Chtiwi Malek
sumber
4

Yah, saya punya masalah yang sama. Model saya bekerja dengan baik di EF CTP5 tetapi gagal membangun di 4.1 dengan kesalahan yang sama "" Validasi gagal untuk satu atau lebih entitas "ketika saya mencoba untuk memulai. Saya menemukan bahwa saya memiliki properti:

public string Comment {get; set;}

Kemudian dalam metode seed pada initializer yang di-override, saya memiliki komentar yang cukup panjang (sekitar 600 huruf).

Saya pikir intinya adalah: di EF 4.1 Anda harus menetapkan anotasi data secara eksplisit dalam beberapa kasus. Bagi saya, pengaturan:

[StringLength(4000)] 
public string Comment {get; set;}

membantu. Ini aneh karena CTP5 tidak punya masalah dengan itu.

Wojciech Kotlinski
sumber
Nah yang saya tanyakan adalah bagaimana cara mendapatkan nama properti yang tepat yang melanggar model. Padahal, saya berhasil mengatasi masalah yang Anda nyatakan menggunakan [StringLength (Int32.MaxValue)] sebagai atribut untuk properti saya (seperti yang disarankan oleh Ladislav Mrnka dan saya membicarakannya dalam pertanyaan ini stackoverflow.com/questions/5346155/… ) Powodzenia! =)
Naz
Ini terlempar ketika saya menambahkan properti baru ke model saya di 4.1. Bekerja dengan sempurna di 4.1 sebelumnya. Aneh. Dipecahkan dengan menambahkan anotasi ke semua properti dalam model.
Roberto Bonini
1

Saya merasa berguna untuk membuat pembungkus SaveChanges yang membuat EntityValidationErrors lebih mudah dibaca:

Public Sub SaveChanges(entities As Entities)

    Try
        entities.SaveChanges()

    Catch ex As DbEntityValidationException

        Dim msg As New StringBuilder
        msg.AppendLine(ex.Message)

        For Each vr As DbEntityValidationResult In ex.EntityValidationErrors
            For Each ve As DbValidationError In vr.ValidationErrors
                msg.AppendLine(String.Format("{0}: {1}", ve.PropertyName, ve.ErrorMessage))
            Next
        Next

        Throw New DbEntityValidationException(msg.ToString, ex.EntityValidationErrors, ex)

    End Try

End Sub

dan kemudian mengubah 'entitas. Simpan Perubahan ()' menjadi 'Simpan Perubahan (entitas)' di seluruh proyek saya

nyengir
sumber
0

Saya tahu ini pertanyaan lama tapi inilah jawaban saya:

catch (DbEntityValidationException ex)
   {
    String.Join("\n", ex.EntityValidationErrors
          .SelectMany(x => x.ValidationErrors)
          .Select(x => x.ErrorMessage)
          .ToArray());
   }

dan jika Anda menggunakan kode terlebih dahulu, Anda juga bisa mengglobal pesan kesalahan Anda menggunakan beberapa file sumber

Sebagai contoh, saya memiliki dua file sumber daya terpisah ini, satu untuk kesalahan dan satu untuk nama properti dan saya menggunakannya sebagai berikut: masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

public class Person 
    {
        [Required(ErrorMessageResourceName = "required",ErrorMessageResourceType =typeof(ErrorMessages))]
        [MaxLength(100,ErrorMessageResourceName = "maxLength", ErrorMessageResourceType = typeof(ErrorMessages))]
        [Display(Name = "FirstName",ResourceType = typeof(Properties))]
        public string FirstName { get; set; }
         }

Seperti yang Anda lihat, saya telah sepenuhnya menerjemahkan pesan kesalahan saya termasuk nama properti, jadi saya kemudian dapat menggunakannya di pengguna nanti misalnya:

masukkan deskripsi gambar di sini

NikiUsefi
sumber