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?

Author: Martin Devillers, 2013-04-04

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ą.

  1. Stwórz cząstkową klasę obok swojego czegoś.Kontekst.plik cs.
  2. Użyj kodu na dole tego posta.
  3. 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/

 403
Author: Martin Devillers,
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);
    }
}
 43
Author: Eric Hirst,
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

 41
Author: Shehab Fawzy,
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
 13
Author: GONeale,
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

 9
Author: Chris Halcrow,
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ą

 5
Author: Calvin,
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.
 3
Author: Luis Toapanta,
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);
}
 0
Author: Juri,
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]}
  1. Http://mattrandle.me/viewing-entityvalidationerrors-in-visual-studio/

  2. Walidacja nie powiodła się dla jednego lub więcej podmiotów. Zobacz właściwość "EntityValidationErrors", aby uzyskać więcej informacji

  3. Http://blogs.infosupport.com/improving-dbentityvalidationexception/

 -2
Author: Atta H.,
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