DbValidationExceptionから正確なエラータイプを取得する


184

EF 4.1のDatabaseInitializer()でモデルを初期化しているときに、この厄介なエラーが発生するという状況になっている"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ツリーにドリルダウンできます。これは、これらのエラーをすばやく洞察するために私が見つけた最も簡単な方法です。

最初のエラーのみを気にし、catchブロックがない可能性があるVisual 2012+ユーザーの場合は、次のこともできます。

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

9
これは他の回答よりも優れています:)
Doug

98
catchブロックがない場合は、置き換えex$exception同じ結果を得ることができます。
Ecyrb 2011

また、あなたが代わる作るexワット/では、あなたのe catch (Exception THIS)IS
Eonasdan

@Ecyrb、ありがとう。グーグルの時間を節約しました。また、検証エラー数が1と表示されている場合でも、実際には配列内に2つの要素があり、2つのエラーがあります。
マトリックス

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

あなたはtry / catchブロックでこれを試すことができますか?

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で正常に動作しましたが、初期化しようとしたときに「1つ以上のエンティティの検証に失敗しました」という同じエラーで4.1でビルドに失敗しました。

public string Comment {get; set;}

次に、オーバーライドされた初期化子のシードメソッドで、かなり長い(約600文字)コメントがありました。

ポイントは次のとおりです。EF4.1では、場合によっては明示的にデータ注釈を設定する必要あります。私にとって、設定:

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

助けた。CTP5には問題がなかったので奇妙です。


さて、私が求めていたのは、モデルを壊している正確なプロパティ名を取得する方法です。しかし、私はプロパティの属性として[StringLength(Int32.MaxValue)]を使用して述べた問題をなんとか克服しました(Ladislav Mrnkaによって提案され、この質問でそれについて話しましたstackoverflow.com/questions/5346155/…)ポウォドツェニア!=)
Naz

これは、4.1でモデルに新しいプロパティを追加したときにスローされました。以前は4.1で完全に機能していました。変だ。モデルのすべてのプロパティに注釈を追加することで解決しました。
Roberto Bonini 2011年

1

EntityValidationErrorsを読みやすくするSaveChangesラッパーを作成すると便利です。

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

プロジェクト全体で 'entities.SaveChanges()'を 'SaveChanges(entities)'に変更しました


0

私はそれが古い質問であることを知っていますが、これが私の答えです:

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

最初にコードを使用する場合は、複数のリソースファイルを使用してエラーメッセージをグローバル化することもできます

たとえば、エラー用とプロパティ名用の2つの個別のリソースファイルがあり、次のように使用します。 ここに画像の説明を入力してください ここに画像の説明を入力してください

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.