エンティティフレームワークコアDbUpdateException詳細情報

c# entity-framework-core integration-testing

質問

私はちょうど私の完全な.net 4.5.2プロジェクトでEFコアを使い始めています。新しい学生を入れることができるかどうかを検証するための統合テストをしようとしています。

問題は、データベースに挿入されない理由について、例外からより良い情報を得ることができるようにすることです。

私の統合テストコードは次のとおりです。

    [Fact]
    public void save_the_new_student_to_the_database()
    {
        var fixture = new Fixture();
        var optionsBuilder = new DbContextOptionsBuilder<TestDbContext>();
        //optionsBuilder.UseInMemoryDatabase();
        optionsBuilder.UseSqlServer("Server = (localdb)\\mssqllocaldb; Database = afmil_Test_next; Trusted_Connection = True; "
                );

        using (var context = new TestDbContext(optionsBuilder.Options))
        {
            var command = fixture.Create<PostRegisterStudentCommand>();
            var handler = new PostRegisterStudentCommandHandler(context);

            try
            {
                handler.Handle(command);
            }
            catch (DbUpdateException e)
            {
                var sb = new StringBuilder();
                sb.AppendLine($"DbUpdateException error details - {e?.InnerException?.InnerException?.Message}");

                foreach (var eve in e.Entries)
                {
                    sb.AppendLine($"Entity of type {eve.Entity.GetType().Name} in state {eve.State} could not be updated");
                }

                sb.ShouldBeNull();
            }

            var dbStudent = context.Students.FirstOrDefault();
            dbStudent.ShouldNotBeNull();
            dbStudent.User.FirstName.ShouldBe(command.FirstName);
        }

    }

私はEF 6のstackoverflowの答えから例外をキャッチ部分を得た。

私はEFコアで実体検証問題(EF6からのDbEntityValidationException)を抽出する例を見つけるために考えることができるすべてを検索しましたが、動作するように見えるものは何も見つかりません。

このEF Core githubの問題からの示唆として、私はこのようなアノテーション検証をいくつか試みました。しかし、これは私の生徒のオブジェクトでデータベースが持っていた問題を見つけることはできませんでした。

人気のある回答

実際、EF7はEF6で利用可能であるという検証が欠けている。モデルが保存される前に検証が行われる(そして、DB制約も安全ネットとして使用される)ので、これは設計上の選択肢のようです。

この資料では、データを保存する前に検証を手動で実行する方法を示します。ただし、これはデータアノテーションでのみ機能することに注意してください。私のわずかに変更されたバージョンは次のとおりです:

public void Validate()
{
    var entities = ChangeTracker.Entries()
        .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
        .Select(e => e.Entity)
        .ToList();

    foreach (var entity in entities)
    {
        var validationContext = new ValidationContext(entity);
        Validator.ValidateObject(entity, validationContext, validateAllProperties: true);
    }
}

私のアドバイスは、次のような例外の両方の型(検証とデータベース)を処理するメソッドを持つことです。

try
{
    Validate();
    Context.SaveChanges();
}
catch(ValidationException exc)
{
    Logger.LogError(exc, $"{nameof(SaveChanges)} validation exception: {exc?.Message}");
    return false;
}
catch (DbUpdateException exc)
{
    Logger.LogError(exc, $"{nameof(SaveChanges)} db update error: {exc?.InnerException?.Message}");
    return false;
}


Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ