[英]Entity Framework Core DbUpdateException detailed information
我剛剛在我的完整 .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 answer 中得到了異常捕獲部分。
我已經搜索了我能想到的所有內容,以在 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);
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;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.