DbEntityValidationException-Jak mogę łatwo stwierdzić, co spowodowało błąd?
Mam projekt, który używa encji Framework. Podczas wywoływania {[0] } Na moim DbContext
, dostaję następujący wyjątek:
System.Data./ Align = "left" / / Align = "left" / DbEntityValidationException: Validation nie powiodło się dla jednego lub więcej podmiotów. Patrz: własność "EntityValidationErrors" po więcej szczegółów.
Wszystko jest w porządku, ale nie chcę dołączać debuggera za każdym razem, gdy wystąpi ten wyjątek. Co więcej, w środowiskach produkcyjnych nie mogę łatwo dołączyć debuggera, więc mam aby zrobić wiele, aby odtworzyć te błędy.
Jak mogę zobaczyć szczegóły ukryte w DbEntityValidationException
?
9 answers
Najprostszym rozwiązaniem jest nadpisanie SaveChanges
na klasie encji. Możesz złapać DbEntityValidationException
, rozpakować rzeczywiste błędy i utworzyć nową DbEntityValidationException
z ulepszoną wiadomością.
- Stwórz cząstkową klasę obok swojego czegoś.Kontekst.plik cs.
- Użyj kodu na dole tego posta. To wszystko. Twoja implementacja automatycznie użyje nadpisanych przełączników SaveChanges bez konieczności refakturowania.
Twój komunikat o wyjątku będzie teraz wyglądał następująco to:
System.Data./ Align = "left" / / Align = "left" / DbEntityValidationException: Validation nie powiodło się dla jednego lub więcej podmiotów. Patrz: własność "EntityValidationErrors" po więcej szczegółów. Błędy walidacji to: numer Fonenumber pola musi być typu string lub array o maksymalnej długości "12"; Pole LastName jest wymagane.
Możesz upuścić nadpisane SaveChanges w dowolnej klasie, która dziedziczy z DbContext
:
public partial class SomethingSomethingEntities
{
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException ex)
{
// Retrieve the error messages as a list of strings.
var errorMessages = ex.EntityValidationErrors
.SelectMany(x => x.ValidationErrors)
.Select(x => x.ErrorMessage);
// Join the list to a single string.
var fullErrorMessage = string.Join("; ", errorMessages);
// Combine the original exception message with the new one.
var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);
// Throw a new DbEntityValidationException with the improved exception message.
throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
}
}
}
DbEntityValidationException
zawiera również byty, które spowodowało błędy walidacji. Więc jeśli potrzebujesz jeszcze więcej informacji, możesz zmienić powyższy kod na informacje wyjściowe o tych podmiotach.
Zobacz też: http://devillers.nl/improving-dbentityvalidationexception/
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-09 01:47:10
Jak zaznaczył Martin, więcej informacji znajduje się w DbEntityValidationResult
. Uznałem, że przydatne jest umieszczanie zarówno nazwy mojej klasy POCO, jak i nazwy właściwości w każdej wiadomości i chciałem uniknąć konieczności pisania niestandardowych atrybutów ErrorMessage
na wszystkich moich tagach [Required]
tylko w tym celu.
Następujące poprawki do kodu Martina zadbały o te szczegóły dla mnie:
// Retrieve the error messages as a list of strings.
List<string> errorMessages = new List<string>();
foreach (DbEntityValidationResult validationResult in ex.EntityValidationErrors)
{
string entityName = validationResult.Entry.Entity.GetType().Name;
foreach (DbValidationError error in validationResult.ValidationErrors)
{
errorMessages.Add(entityName + "." + error.PropertyName + ": " + error.ErrorMessage);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-07 16:31:26
Aby wyświetlić kolekcję EntityValidationErrors
, dodaj następujące wyrażenie Watch do okna Watch.
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors
Używam visual studio 2013
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-13 12:45:47
Gdy jesteś w trybie debugowania w bloku catch {...}
Otwórz okno " QuickWatch "(ctrl+alt+q ) i wklej tam:
((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors
To pozwoli Ci wwiercić się w drzewo. To najprostszy sposób, jaki znalazłem, aby uzyskać natychmiastowy wgląd w te błędy.
Dla użytkowników Visual 2012+, którzy dbają tylko o pierwszy błąd i mogą nie mieć bloku catch
, możesz nawet zrobić:
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors.First().ValidationErrors.First().ErrorMessage
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-14 23:26:35
Aby szybko znaleźć sensowny komunikat o błędzie, sprawdzając błąd podczas debugowania:
-
Dodaj szybki zegarek dla:
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors
-
Przewierć się w EntityValidationErrors tak:
(element kolekcji np. [0])> ValidationErrors > (element kolekcji np. [0]) > ErrorMessage
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-20 00:21:54
W rzeczywistości jest to tylko problem z walidacją, EF najpierw zweryfikuje właściwości encji przed dokonaniem jakichkolwiek zmian w bazie danych. Tak więc, EF sprawdzi, czy wartość właściwości jest poza zakresem, jak podczas projektowania tabeli. Table_Column_UserName to varchar (20). Ale w EF wpisałeś wartość dłuższą niż 20. Lub, w innych przypadkach, jeśli kolumna nie pozwala na Null. Tak więc w procesie walidacji musisz ustawić wartość na kolumnę not null, bez względu na to, czy jesteś / align = "left" / Osobiście podoba mi się odpowiedź Leniel Macaferi. Może pokazać szczegóły problemów z walidacją
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 01:15:41
Myślę, że "rzeczywiste błędy walidacji" mogą zawierać poufne informacje i to może być powód, dla którego Microsoft zdecydował się umieścić je w innym miejscu (właściwości). Rozwiązanie zaznaczone tutaj jest praktyczne, ale należy zachować ostrożność.
Wolałbym utworzyć metodę rozszerzenia. Więcej powodów do tego:
- Zachowaj oryginalny ślad stosu
- postępuj zgodnie z zasadą otwartą/zamkniętą (tj.: Mogę używać różnych wiadomości dla różnych rodzajów dzienników)
- w produkcji środowiska Mogą istnieć inne miejsca(np.: other dbcontext), gdzie może zostać rzucone wywołanie DbEntityValidationException.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-18 22:07:14
Dla Azure Functions używamy tego prostego rozszerzenia do Microsoft.Rozszerzenia.Logowanie.ILogger
public static class LoggerExtensions
{
public static void Error(this ILogger logger, string message, Exception exception)
{
if (exception is DbEntityValidationException dbException)
{
message += "\nValidation Errors: ";
foreach (var error in dbException.EntityValidationErrors.SelectMany(entity => entity.ValidationErrors))
{
message += $"\n * Field name: {error.PropertyName}, Error message: {error.ErrorMessage}";
}
}
logger.LogError(default(EventId), exception, message);
}
}
I przykładowe użycie:
try
{
do something with request and EF
}
catch (Exception e)
{
log.Error($"Failed to create customer due to an exception: {e.Message}", e);
return await StringResponseUtil.CreateResponse(HttpStatusCode.InternalServerError, e.Message);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-15 16:27:15
Użyj try block w kodzie jak
try
{
// Your code...
// Could also be before try if you know the exception occurs in SaveChanges
context.SaveChanges();
}
catch (DbEntityValidationException e)
{
foreach (var eve in e.EntityValidationErrors)
{
Console.WriteLine("Entity of type \"{0}\" in state \"{1}\" has the following validation errors:",
eve.Entry.Entity.GetType().Name, eve.Entry.State);
foreach (var ve in eve.ValidationErrors)
{
Console.WriteLine("- Property: \"{0}\", Error: \"{1}\"",
ve.PropertyName, ve.ErrorMessage);
}
}
throw;
}
Tutaj możesz sprawdzić szczegóły]}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-18 15:32:10