1つ以上のエンティティの検証が失敗しました。詳細については、「EntityValidationErrors」プロパティを参照してください


804

コードを最初に使用する方法でデータベースをシードするときに、このエラーが発生します。

1つ以上のエンティティの検証が失敗しました。詳細については、「EntityValidationErrors」プロパティを参照してください。

正直なところ、検証エラーの内容を確認する方法がわかりません。Visual Studioは、8つのオブジェクトを含む配列であるため、8つの検証エラーがあることを示しています。

これは以前のモデルで機能していましたが、以下で説明するいくつかの変更を加えました。

  • Statusという列挙があり、Statusというクラスに変更しました
  • ApplicantsPositionHistoryクラスを変更して、同じテーブルへの2つの外部キーを設定しました

長いコードはすみませんが、すべて貼り付ける必要があります。例外は次のコードの最後の行でスローされます。

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

回答:


1237

正直なところ、検証エラーの内容を確認する方法がわかりません。Visual Studioは、8つのオブジェクトを含む配列であるため、8つの検証エラーがあることを示しています。

実際、デバッグ中にVisual Studioでその配列にドリルすると、エラーが表示されます。ただし、例外をキャッチして、エラーをログストアまたはコンソールに書き込むこともできます。

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は、正常に検証できなかったエンティティを表すコレクションであり、エンティティValidationErrorsごとの内部コレクションは、プロパティレベルのエラーのリストです。

これらの検証メッセージは通常、問題の原因を見つけるのに十分役立ちます。

編集する

いくつかのわずかな改善:

問題のプロパティのは、次のように内部ループに含めることができます。

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

デバッグDebug.Writeが望ましいかもしれませんがConsole.WriteLineコンソールアプリケーションだけでなく、あらゆる種類のアプリケーションでます(以下のコメントでの@Bartのコメントに感謝)。

本番環境にあり、例外ロギングにElmahを使用するWebアプリケーションの場合、カスタム例外を作成して上書きすることが非常に便利であることがわかりましたSaveChangesこの新しい例外をスローするために。

カスタム例外タイプは次のようになります。

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

そしてSaveChanges、次の方法で上書きすることができます:

public class MyContext : DbContext
{
    // ...

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

いくつかの注意:

  • ElmahがWebインターフェースまたは送信したEメール(構成済みの場合)に表示する黄色のエラー画面で、検証の詳細がメッセージの上部に直接表示されるようになりました。

  • 上書きするMessage代わりにカスタム例外でプロパティを上書きするToString()と、標準のASP.NETの「死の黄色の画面(YSOD)」でもこのメッセージが表示されるという利点があります。Elmahとは対照的に、YSODは明らかにを使用しませんToString()が、どちらもMessageプロパティを表示します。

  • オリジナルDbEntityValidationExceptionを内部例外としてラップすることにより、オリジナルのスタックトレースが引き続き使用可能であり、ElmahおよびYSODに表示されます。

  • 行にブレークポイントを設定すると、検証コレクションにドリルダウンする代わりにthrow newException;newException.Messageプロパティをテキストとして単に検査できます。これは、少し厄介であり、誰にとっても簡単に機能しないようです(以下のコメントを参照)。


87
例外にドリルダウンしても何も起こりません。DbEntityValidationResultがあるというだけですが、拡張できません!!
Shumii

30
@Shumii 例外を拡大するには、この回答を参照してください。
Cavyn VonDeylen 2012年

18
エレガントなソリューションを拡張するだけです。独自のDbContextクラスのsavechangesメソッドをオーバーライドしてから、try catchブロックを追加することができます。tryブロックは保存しようとするだけで(base.SaveChanges())、catchブロックはDbEntityValidationExceptionのみをキャッチします。このように、変更を保存するすべての場所に追加する必要はありません。
ミルトン

7
これにより、ベーコンを何度も節約できました。私は一度しか賛成できませんでした。私がこれをコピーして貼り付けるたびに、彼らが私に賛成票を投じることを望みました。
デイモンドレイク

5
+2コード。確かに救世主:) -1を使用するためConsole.WriteLine、より多くの人々がWebプロジェクトを作成し、現在はコンソールアプリを作成していて、Debug.Write両方で動作していると思います...
Bart

459

デバッグ中にVisual Studioからコードを記述することなく、catchブロックでさえも行うことができます。

次の名前の時計を追加するだけです。

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

ウォッチ式$exceptionは、キャッチされて変数に割り当てられていなくても、現在のコンテキストでスローされた例外を表示します。

http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/に基づく


39
+1の方法より優れたソリューションで、コードの変更は必要ありません。クール
Justas 14

4
+1これはとても便利です。try / catchブロックも必要ありません。VSが壊れて失敗したら、ウォッチリストにこれを貼り付けてください。目の前に検証エラーがあります。
theyetiman 2014年

40
年に数回、これを行う方法を忘れてこの答えを見つける
Justin Moore

3
@zairja私はvb.netでテストしていませんが、変数はvb.netにもmsdn.microsoft.com/en-us/library/ms164891.aspxで定義されているようですが、キャストはおそらくvb.netに対して定義されています。代わりに、DirectCast($ exception、System.Data.Entity.Validation.DbEntityValidationException)を実行する必要があります
yoel halb

2
「感謝」はコメントで歓迎されないことを知っていますが、時間の無駄な時間を防ぐために...ありがとう!
Luther

105

これは実際にコードを書かなくてもそれを行うことができます:

catchブロックで、次のコード行にブレークポイントを追加します。

catch (Exception exception)
{

}

ここにカーソルを合わせるexceptionか追加して、Watch以下に示すように例外の詳細に移動します。このエラーは通常、テーブルの制約に違反した場合に発生するため、どの特定の列が問題を引き起こしているかがわかります。

ここに画像の説明を入力してください

大きな画像


4
このアプローチは非常に単純で、IDEを利用します:)
dsnunez

3
これは迅速でシンプルで、IDEを利用でき、時間を大幅に節約できるので、優れたソリューションです。
maxshuty 2015年

2
Iこの方法のように、「どのようにコーダされるように、コードをしない」
オープンで自由な

1
ありがとうございました。これは簡単ですが、IDEを使用して例外を表示するのは素晴らしいことです。
Thomas.Benz 2017年

完璧なソリューション
Neeraj Singh Chouhan

46

ここでは、Visual StudioでEntityValidationErrorsの内容を確認する方法を示します(追加のコードを記述せずに)。つまり、IDEでのデバッグ中に

問題?

そうです、Visual Studioデバッガーの[詳細表示]ポップアップには、EntityValidationErrorsコレクション内の実際のエラーは表示されません。

ここに画像の説明を入力してください

ソリューション!

クイックウォッチウィンドウに次の式を追加して、[ 再評価 ]をクリックします。

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

私の場合、コレクションのValidationErrors List内部にどのように展開できるかを見てくださいEntityValidationErrors

ここに画像の説明を入力してください

参照: mattrandle.meブログ投稿@ yoelの回答


3
なぜこれが修正されていないのですか?それは何か他のものではなくエラーを表示するはずです
Geomorillo

2
検証エラーは、プロパティエラーを示します。件名フィールドは必須です。良い回答です。ありがとう
hamzeh.hanandeh

1
すごい!それは私の夜を救った!:)
Patrick、

1
これは時計の正確なエラーを視覚化するスマートな方法です...ありがとう!
Qwerty

39

時計を追加することなく最初のエラーをすばやく確認するには、これをイミディエイトウィンドウに貼り付けます。

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

1
$ exception.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage)を使用してそれらすべてを取得することもできます:)イミディエイトウィンドウを使用するのが最良の答えです
chrispepper1989

15

働く人のために 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 {...}ブロック内でデバッグモードになっている間に、[QuickWatch]ウィンドウ(ctrl+ alt+ q)を開き、そこに貼り付けます。

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

または:

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

try / catchに参加していない場合、または例外オブジェクトにアクセスできない場合。

これにより、ValidationErrorsツリーにドリルダウンできます。これは、これらのエラーをすばやく洞察するために私が見つけた最も簡単な方法です。


10

単に一般的な例外をキャッチしているだけの場合は、これをDbEntityValidationExceptionとしてキャストすると便利です。です。このタイプの例外にはValidation Errorsプロパティがあり、それらをさらに拡張していくと、すべての問題が見つかります。

たとえば、キャッチにブレークポイントを設定した場合、次のものをウォッチにスローできます。

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

エラーの例は、フィールドがnullを許可せず、null文字列がある場合、フィールドが必須であると表示されます。


9

データベーステーブルのフィールド長を確認するだけです。入力テキストが列フィールドのデータ型の長さを超えています


9

デバッグでは、これをQuickWatch式エバリュエーターの入力フィールドに入力できます。

context.GetValidationErrors()

8

@Slaumaからの回答は本当に素晴らしいですが、ComplexTypeプロパティが無効な場合は機能しないことがわかりました。

たとえばPhone、複合型のプロパティがあるとしますPhoneNumber。場合AreaCodeプロパティが無効である、でプロパティ名はve.PropertyNames「Phone.AreaCode」です。これにより、への呼び出しeve.Entry.CurrentValues<object>(ve.PropertyName)が失敗します。

これを修正するには、各.でプロパティ名を分割し、結果のプロパティ名の配列を再帰的に処理します。最後に、チェーンの最後に到達すると、プロパティの値を返すだけです。

以下はComplexTypes FormattedDbEntityValidationExceptionをサポートする@Slaumaのクラスです。

楽しい!

[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
これは非常に現実的なシナリオであり、過去2泊で私を狂わせているため、これを支持していない人が増えることは信じられません。エラー処理が実際にエラーをスローしているものであることに気付いたときに感じる感覚を知っていますか?ああ。
DJ Grossman 2017年

7

Entity.GetType().BaseType.Name名前にすべての16進数字が含まれるタイプではなく、指定したタイプ名が表示されることに注意してください。


7

@Slaumaの回答と@Miltonの提案に従って、この種の例外を処理する(したがって、エラーロギングにログインする)try / catchを使用して、基本クラスのカスタムのsaveメソッドを拡張しました。

// 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()を直接使用できます
Bastien Vandamme

1
AppendFormatを使用する場合は、独自の改行も追加する必要があります。
jocull 16

7

私はこれをイミディエイトウィンドウに書かなければなりませんでした: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]

正確なエラーを深く理解するために!


6

@Slaumaの答えを使用して、コードスニペット(スニペットで囲まれた部分)を作成しました。

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

トライキャッチで例外をキャッチしてから、クイックウォッチまたはctrl + d&ctrl + qを実行すると、EntityValidationErrorsにドリルダウンできます。


5

ちょうど私の2セントを投入...

私のdbConfiguration.cs内で、私のcontext.SaveChanges()メソッドをtry / catchにラップして、エラーを明確に読み取ることができる出力テキストファイルを生成し、このコードもそれらにタイムスタンプを付けます。異なるタイミングで複数のエラーに遭遇する!

        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

私が見つけたもの...「EntityValidationErrors」エラーが発生したとき...それは...データベース「db1」にテーブル「tbladdress」のフィールドが100のサイズを持つ「address1」(つまり、アドレスvarchar(100))を持っていることですnull)そして100文字を超える値を渡していたので、データベースにデータを保存するときにエラーが発生しました...

したがって、フィールドに渡すデータを確認する必要があります。


1
エラーの解決に実際に役立ったため、この回答に感謝します。データベースに保存するテーブルにはすべてのnot null列が含まれていたため、すべての要素にデータを追加してdb.SaveChanges()からエラーが発生することはありませんでした。
BinaryJoe01 2017年

3

これでうまくいきます。

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

ifステートメントにブレークポイントを設定します。その後、デバッグウィンドウでmodelStateを確認できます。すべての値について、エラーがあるかどうか、さらにはエラーメッセージを確認できます。それでおしまい。不要になった場合は、その行を削除するかコメントを付けてください。

これがお役に立てば幸いです。

必要に応じて、デバッグウィンドウに詳細なスクリーンショットを提供できます。


3

他の投稿で述べたように、DbEntityValidationExceptionクラスで例外をキャッチするだけです。これにより、エラーが発生したときに必要なものがすべて提供されます。

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

2

以前にこのエラーに直面しました

エンティティフレームワークでモデルの特定のフィールド更新しようとしたとき

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

上記の回答によると

検証メッセージを見つけました The SignerName field is required.

私のモデルのフィールドを指している

そして、私が見つけたデータベーススキーマをチェックしたとき

ここに画像の説明を入力してください

だからオフcoure ValidationExceptionは上げる権利があります

そしてこのフィールドによれば、私はそれをnullableにしたいです(私はそれをいじった方法を知りません)

Nullを許可するようにそのフィールドを変更しました。これにより、私のコードはこのエラーを再び表示しなくなります

データベースのデータの整合性を無効にすると、このエラーが発生する可能性があります


1
例外が発生するかどうかはここでは重要ではありません。次に、ここでいくつかのコーナーを切ります。データベーススキーマでフィールドが必要な場合、それ以上の値が必要になりますDbEntityValidationException
Gert Arnold

2

渡すフィールド値が有効で、データベースフィールドに従っていることを確認してください。たとえば、特定のフィールドで渡される文字数は、データベーステーブルフィールドで定義された文字よりも少ないです。


1

Windows Authentification and Entity FrameworkIISを使用している場合は、注意して使用してください。authorize

他のすべての動詞とが機能しているときPOSTdb.SaveChangesAsync();、許可なしで試してみましたが、機能せず、このエラーが発生しました。GETDELETE

しかし、AuthorizeAttributeを注釈として追加すると、うまくいきました。

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

1

EntityValidationErrorsを調べるためにforeachループを使用する代わりに、これを行う別の方法を次に示します。もちろん、メッセージを自分の好みにフォーマットすることができます:

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

私の場合は、データベースフィールドの長さが入力フィールドの長さよりも短いためです。

データベーステーブル

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

私の入力

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

の値Username length5、つまりlessthan6

...これは誰かを助けるかもしれません


0

Not Nullテーブルの列に制約があり、挿入/更新操作中にその列の値を渡していないかどうかを確認します。これにより、エンティティフレームワークでこの例外が発生します。


0

私も同じ問題に直面しました。例外がなくなった後、データベースから.edmxを更新しました。



0

また、このエラーに苦労していて、ここのトピックに基づいており、この回答は、何をインポートする必要があるかを理解する必要なく、コピー/貼り付けするスニペットを理解することができました(C#初心者向け)、以下のコード:

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);
    }
  }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.