Получение точного типа ошибки из DbValidationException
У меня есть ситуация, когда я инициализирую мою модель в DatabaseInitializer() для EF 4.1 и получаю эту досадную ошибку "Validation failed for one or more entities. See 'EntityValidationErrors' property for more details."
Итак, я перехожу к этому EntityValidationErrors и есть поле {System.Data.Entity.Validation.DbEntityValidationResult}
, которое не дает мне никакой информации на все о том, в каком поле он не смог инициализировать.
Есть ли способ получить дополнительную информацию об этой ошибке?
Чтобы прояснить ситуацию:
Я знаю, как исправить проблему длины строки. Я спрашиваю, как получить точное имя поля, которое нарушает модель.
Ответы
Ответ 1
Пока вы находитесь в режиме отладки в блоке catch {...}
, откройте окно QuickWatch (ctrl + alt + q) и вставьте туда:
((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors
Это позволит вам развернуться в дерево ValidationErrors
. Это самый простой способ найти мгновенное понимание этих ошибок.
Для пользователей Visual 2012+, которые заботятся только о первой ошибке и могут не иметь блока catch
, вы можете даже сделать:
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage
Ответ 2
Вы можете попробовать это в блоке 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);
}
}
}
Ответ 3
Лучшим решением, на мой взгляд, является централизованное обращение с такими ошибками.
просто добавьте этот метод в основной класс 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, но не смогла построить 4.1 с той же ошибкой "Не удалось выполнить проверку для одного или нескольких объектов", когда я попытался ее инициализировать. Я понял, что у меня есть свойство:
public string Comment {get; set;}
Затем в методе семян в переопределенном инициализаторе у меня было довольно длинное (около 600 писем) комментарий.
Я думаю, что дело в следующем: в EF 4.1 вы имеете, чтобы в некоторых случаях задавать аннотации данных. Для меня настройка:
[StringLength(4000)]
public string Comment {get; set;}
помог. Это странно, поскольку у CTP5 не было проблем с этим.
Ответ 5
Мне было полезно создать оболочку SaveChanges, которая упрощает чтение EntityValidationErrors:
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
а затем изменил "entity.SaveChanges()" на "SaveChanges (сущности)" во всем моем проекте