實體框架核心DbUpdateException詳細信息

c# entity-framework-core integration-testing

我只是在我的完整.net 4.5.2項目中開始使用EF Core,我正在嘗試進行集成測試以驗證我是否可以插入新學生。

問題是,我希望能夠從拋出的異常中獲得更好的信息,以了解它為什麼不插入數據庫。

這是我的集成測試代碼:

    [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 Core中提取實體驗證問題(來自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
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow