我刚刚开始使用我的完整.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)的示例,但找不到任何似乎有效的内容。
根据this EF Core github issue的建议,我尝试进行一些注释验证,例如this。但是这并没有发现数据库与我的学生对象存在的问题。
答案 0 :(得分:0)
事实上,EF7缺乏在EF6中可用的验证。这似乎是一种设计选择,因为在发送模型之前要假设验证(并且DB约束也可以用作安全网)。
This article显示了在保存数据之前如何手动执行验证。但请注意,这仅适用于数据注释。我稍微改变了以下版本:
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;
}