รับประเภทข้อผิดพลาดที่แน่นอนจาก DbValidationException


184

ฉันมีสถานการณ์ที่ฉันเริ่มต้นรูปแบบของฉันใน DatabaseInitializer () เพื่อ EF 4.1 และได้รับข้อผิดพลาดที่น่ารำคาญนี้"Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."ดังนั้นฉันไป EntityValidationErrors นี้และมีสนาม{System.Data.Entity.Validation.DbEntityValidationResult}ซึ่งทำให้ผมไม่มีข้อมูลที่เกี่ยวกับสิ่งที่ข้อมูลมันก็ไม่สามารถที่จะเริ่มต้น . มีวิธีรับข้อมูลเพิ่มเติมเกี่ยวกับข้อผิดพลาดนี้หรือไม่

หากต้องการล้างสิ่งต่างๆออก:

ฉันรู้วิธีแก้ไขปัญหาความยาวสตริง สิ่งที่ฉันถามคือฉันจะได้รับชื่อเขตข้อมูลที่แน่นอนที่ทำลายแบบจำลองได้อย่างไร

คำตอบ:


377

ในขณะที่คุณอยู่ในโหมดแก้ไขข้อบกพร่องภายในcatch {...}บล็อกเปิดหน้าต่าง "QuickWatch" ( ctrl+ alt+ q) และวางใน:

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

นี้จะช่วยให้คุณสามารถเจาะลึกลงไปในValidationErrorsต้นไม้ มันเป็นวิธีที่ง่ายที่สุดที่ฉันพบว่าได้รับข้อมูลเชิงลึกเกี่ยวกับข้อผิดพลาด

สำหรับผู้ใช้ Visual 2012+ ที่สนใจเฉพาะข้อผิดพลาดแรกและอาจไม่มีcatchบล็อกคุณสามารถทำได้:

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

9
นี้จะดีกว่าคำตอบอื่น ๆ :)
ดั๊ก

98
หากคุณไม่มี catch catch คุณสามารถแทนที่exด้วย$exceptionและรับผลลัพธ์เดียวกัน
Ecyrb

ยังให้แน่ใจว่าคุณแทนที่exด้วย w / e ของคุณcatch (Exception THIS)เป็น
Eonasdan

@Ecyrb ขอบคุณ คุณประหยัดเวลาในการใช้ Google นอกจากนี้แม้ว่าจำนวนข้อผิดพลาดในการตรวจสอบความถูกต้องจะแสดงเป็น 1 แต่ก็มีองค์ประกอบสองอย่างในอาร์เรย์ที่มีข้อผิดพลาดสองข้อ
เมทริกซ์

3
สำหรับผู้ที่ไม่ได้อ้างอิง System.Linq และใช้หน้าต่างทันที:System.Linq.Enumerable.ToList(System.Linq.Enumerable.ToList(((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors)[0].ValidationErrors)[0].ErrorMessage
jpsimard-nyx

124

คุณสามารถลองสิ่งนี้ในบล็อกลอง / จับได้หรือไม่

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

11

ทางออกที่ดีที่สุดในความคิดของฉันคือการจัดการข้อผิดพลาดในลักษณะรวมศูนย์

เพียงเพิ่มวิธีนี้ในDbContextคลาสหลัก:

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

สิ่งนี้จะเขียนทับSaveChanges()วิธีของบริบทของคุณและคุณจะได้รับรายการที่คั่นด้วยเครื่องหมายจุลภาคที่มีข้อผิดพลาดในการตรวจสอบความถูกต้องเอนทิตีทั้งหมด

หวังว่านี่จะเป็นประโยชน์


4

ฉันมีปัญหาเดียวกัน แบบจำลองของฉันทำงานได้ดีใน EF CTP5 แต่ล้มเหลวในการสร้างใน 4.1 โดยมีข้อผิดพลาดเดียวกัน "" การตรวจสอบล้มเหลวสำหรับเอนทิตี้อย่างน้อยหนึ่งรายการ "เมื่อฉันพยายามทำให้เป็นจริงฉันคิดว่ามีทรัพย์สิน:

public string Comment {get; set;}

จากนั้นในวิธีการเมล็ดใน initializer แทนที่ฉันมีความคิดเห็นค่อนข้างยาว (ประมาณ 600 ตัวอักษร)

ฉันคิดว่าประเด็นคือใน EF 4.1 คุณต้องตั้งค่าคำอธิบายประกอบข้อมูลอย่างชัดเจนในบางกรณี สำหรับฉันการตั้งค่า:

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

ช่วย มันแปลกเพราะ CTP5 ไม่มีปัญหากับมัน


สิ่งที่ฉันถามคือฉันจะได้รับชื่อคุณสมบัติที่แน่นอนที่ทำลายโมเดลได้อย่างไร แม้ว่าฉันจัดการเพื่อเอาชนะปัญหาที่คุณระบุโดยใช้ [StringLength (Int32.MaxValue)] เป็นแอตทริบิวต์สำหรับคุณสมบัติของฉัน (ตามที่ Ladislav Mrnka แนะนำและฉันได้พูดถึงปัญหานี้ในคำถามstackoverflow.com/questions/5346155/ ) Powodzenia! =)
Naz

สิ่งนี้เกิดขึ้นเมื่อฉันเพิ่มคุณสมบัติใหม่ในโมเดลของฉันใน 4.1 เคยทำงานอย่างสมบูรณ์แบบใน 4.1 มาก่อน แปลก. แก้ไขได้โดยการเพิ่มคำอธิบายประกอบให้กับคุณสมบัติทั้งหมดในโมเดล
Roberto Bonini

1

ฉันพบว่ามีประโยชน์ในการสร้าง wrapper ของ SaveChanges ซึ่งทำให้ EntityValidationErrors สามารถอ่านได้มากขึ้น:

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

และจากนั้นเปลี่ยน 'เอนทิตี SaveChanges ()' เป็น 'SaveChanges (เอนทิตี)' ในโครงการทั้งหมดของฉัน


0

ฉันรู้ว่ามันเป็นคำถามเก่า แต่นี่คือคำตอบของฉัน:

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

และถ้าคุณใช้รหัสก่อนคุณสามารถทำให้ข้อความแสดงข้อผิดพลาดเป็นโลกาภิวัตน์โดยใช้ไฟล์ทรัพยากรหลายไฟล์

เช่นฉันมีสองไฟล์ทรัพยากรแยกต่างหากหนึ่งสำหรับข้อผิดพลาดและหนึ่งสำหรับชื่อคุณสมบัติและฉันใช้ดังต่อไปนี้: ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่

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

อย่างที่คุณเห็นฉันได้แปลข้อความแสดงข้อผิดพลาดของฉันอย่างครบถ้วนรวมถึงชื่อคุณสมบัติดังนั้นฉันจึงสามารถใช้พวกเขาในภายหลังได้เช่น:

ป้อนคำอธิบายรูปภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.