c# - tutorial - paging asp net mvc




Die Überprüfung ist für eine oder mehrere Entitäten fehlgeschlagen, während Änderungen an der SQL Server-Datenbank mit Entity Framework gespeichert wurden (11)

Ich möchte meine Edit zu Datenbank speichern und ich verwende Entity FrameWork Code-First in ASP.NET MVC 3 / C #, aber ich bekomme Fehler. In meiner Event-Klasse habe ich DateTime und TimeSpan Datentypen aber in meiner Datenbank habe ich Datum und Uhrzeit. Könnte das der Grund sein? Wie kann ich vor dem Speichern von Änderungen in der Datenbank den entsprechenden Datentyp im Code umsetzen?

public class Event
{
    public int EventId { get; set; }
    public int CategoryId { get; set; }
    public int PlaceId { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
    public DateTime EventDate { get; set; }
    public TimeSpan StartTime { get; set; }
    public TimeSpan EndTime { get; set; }
    public string Description { get; set; }
    public string EventPlaceUrl { get; set; }
    public Category Category { get; set; }
    public Place Place { get; set; }
}

Methode im Controller >>>> Problem bei storeDB.SaveChanges ();

// POST: /EventManager/Edit/386        
[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    var theEvent = storeDB.Events.Find(id);

    if (TryUpdateModel(theEvent))
    {
        storeDB.SaveChanges();
        return RedirectToAction("Index");
    }
    else
    {
        ViewBag.Categories = storeDB.Categories.OrderBy(g => g.Name).ToList();
        ViewBag.Places = storeDB.Places.OrderBy(a => a.Name).ToList();
        return View(theEvent);
    }
}

mit

public class EventCalendarEntities : DbContext
{
    public DbSet<Event> Events { get; set; }
    public DbSet<Category> Categories { get; set; }
    public DbSet<Place> Places { get; set; } 
}

SQL Server 2008 R2-Datenbank / T-SQL

EventDate (Datatype = date)  
StartTime (Datatype = time)  
EndTime (Datatype = time)  

HTTP-Formular

EventDate (Datatype = DateTime) e.g. 4/8/2011 12:00:00 AM  
StartTime (Datatype = Timespan/time not sure) e.g. 08:30:00  
EndTime (Datatype = Timespan/time not sure) e.g. 09:00:00  

Serverfehler in '/' Anwendung.

Die Validierung ist für eine oder mehrere Entitäten fehlgeschlagen. Weitere Informationen finden Sie unter Eigenschaft 'EntityValidationErrors'.

Beschreibung: Bei der Ausführung der aktuellen Webanforderung ist eine nicht behandelte Ausnahme aufgetreten. Bitte überprüfen Sie die Stack-Trace für weitere Informationen über den Fehler und wo es aus dem Code stammt.

Ausnahmedetails: System.Data.Entity.Validation.DbEntityValidationException: Die Überprüfung für eine oder mehrere Entitäten ist fehlgeschlagen. Weitere Informationen finden Sie unter Eigenschaft 'EntityValidationErrors'.

Quellfehler:

Line 75:             if (TryUpdateModel(theEvent))
Line 76:             {
Line 77:                 storeDB.SaveChanges();
Line 78:                 return RedirectToAction("Index");
Line 79:             }

Quelldatei: C: \ sep \ MvcEventCalendar \ MvcEventCalendar \ Controller \ EventManagerController.cs Zeile: 77

Stack Trace:

[DbEntityValidationException: Die Überprüfung für eine oder mehrere Entitäten ist fehlgeschlagen. Weitere Informationen finden Sie unter Eigenschaft 'EntityValidationErrors'.]


Als Verbesserung für Praveen und Tony verwende ich eine Überschreibung:

public partial class MyDatabaseEntities : DbContext
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException dbEx)
        {
            foreach (var validationErrors in dbEx.EntityValidationErrors)
            {
                foreach (var validationError in validationErrors.ValidationErrors)
                {
                    Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
                        validationErrors.Entry.Entity.GetType().FullName,
                        validationError.PropertyName,
                        validationError.ErrorMessage);
                }
            }

            throw;  // You can also choose to handle the exception here...
        }
    }
}

Dies kann durch die Eigenschaft verursacht werden, die nicht vom Modell aufgefüllt wird. Stattdessen wird sie von Controller .. gefüllt, was zu diesem Fehler führen kann. Lösung hierfür ist die Eigenschaft vor dem Anwenden der ModelState-Validierung zuzuweisen. und diese zweite Annahme ist. Möglicherweise haben Sie bereits Daten in Ihrer Datenbank und versuchen, sie zu aktualisieren, aber jetzt abzurufen.


Diese Implementation Wrap Entity Ausnahme Ausnahme mit Detailtext. Es behandelt DbEntityValidationException , DbUpdateException , datetime2 Bereichsfehler (MS SQL) und enthält den Schlüssel der ungültigen Entität in der Nachricht (nützlich, wenn viele Entitäten bei einem SaveChanges Aufruf SaveChanges ).

Überschreibe zuerst SaveChanges in der DbContext-Klasse:

public class AppDbContext : DbContext
{
    public override int SaveChanges()
    {
        try
        {
            return base.SaveChanges();
        }
        catch (DbEntityValidationException dbEntityValidationException)
        {
            throw ExceptionHelper.CreateFromEntityValidation(dbEntityValidationException);
        }
        catch (DbUpdateException dbUpdateException)
        {
            throw ExceptionHelper.CreateFromDbUpdateException(dbUpdateException);
        }
    }   

    public override async Task<int> SaveChangesAsync(CancellationToken cancellationToken)
    {
        try
        {
            return await base.SaveChangesAsync(cancellationToken);
        }
        catch (DbEntityValidationException dbEntityValidationException)
        {
            throw ExceptionHelper.CreateFromEntityValidation(dbEntityValidationException);
        }
        catch (DbUpdateException dbUpdateException)
        {
            throw ExceptionHelper.CreateFromDbUpdateException(dbUpdateException);
        }
    }

ExceptionHelper-Klasse:

public class ExceptionHelper
{
    public static Exception CreateFromEntityValidation(DbEntityValidationException ex)
    {
        return new Exception(GetDbEntityValidationMessage(ex), ex);
    }

    public static string GetDbEntityValidationMessage(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);
        return exceptionMessage;
    }

    public static IEnumerable<Exception> GetInners(Exception ex)
    {
        for (Exception e = ex; e != null; e = e.InnerException)
            yield return e;
    }

    public static Exception CreateFromDbUpdateException(DbUpdateException dbUpdateException)
    {
        var inner = GetInners(dbUpdateException).Last();
        string message = "";
        int i = 1;
        foreach (var entry in dbUpdateException.Entries)
        {
            var entry1 = entry;
            var obj = entry1.CurrentValues.ToObject();
            var type = obj.GetType();
            var propertyNames = entry1.CurrentValues.PropertyNames.Where(x => inner.Message.Contains(x)).ToList();
            // check MS SQL datetime2 error
            if (inner.Message.Contains("datetime2"))
            {
                var propertyNames2 = from x in type.GetProperties()
                                        where x.PropertyType == typeof(DateTime) ||
                                            x.PropertyType == typeof(DateTime?)
                                        select x.Name;
                propertyNames.AddRange(propertyNames2);
            }

            message += "Entry " + i++ + " " + type.Name + ": " + string.Join("; ", propertyNames.Select(x =>
                string.Format("'{0}' = '{1}'", x, entry1.CurrentValues[x])));
        }
        return new Exception(message, dbUpdateException);
    }
}

Dieser Code half mir, mein Problem zu finden, als ich Probleme mit meiner Entity VAlidation Erros hatte. Es sagte mir das genaue Problem mit meiner Entity Definition. Versuchen Sie folgenden Code, den Sie abdecken müssen StoreDB.SaveChanges (); im folgenden Versuch, Block zu fangen.

  try
{
         if (TryUpdateModel(theEvent))
         {
             storeDB.SaveChanges();
             return RedirectToAction("Index");
         }
}
catch (System.Data.Entity.Validation.DbEntityValidationException dbEx)
{
    Exception raise = dbEx;
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
        foreach (var validationError in validationErrors.ValidationErrors)
        {
            string message = string.Format("{0}:{1}", 
                validationErrors.Entry.Entity.ToString(),
                validationError.ErrorMessage);
            // raise a new exception nesting
            // the current instance as InnerException
            raise = new InvalidOperationException(message, raise);
        }
    }
    throw raise;
}

Falls Sie Klassen mit denselben Eigenschaftennamen haben, ist hier eine kleine Erweiterung von Praveens Antwort:

 catch (DbEntityValidationException dbEx)
 {
    foreach (var validationErrors in dbEx.EntityValidationErrors)
    {
       foreach (var validationError in validationErrors.ValidationErrors)
       {
          Trace.TraceInformation(
                "Class: {0}, Property: {1}, Error: {2}",
                validationErrors.Entry.Entity.GetType().FullName,
                validationError.PropertyName,
                validationError.ErrorMessage);
       }
    }
 }

Hier ist eine Erweiterung zu Tonys Erweiterung ... :-)

Wenn Sie für Entity Framework 4.x den Namen und den Wert des Schlüsselfelds abrufen möchten, damit Sie wissen, bei welcher Entitätsinstanz (DB-Datensatz) das Problem auftritt, können Sie Folgendes hinzufügen. Dies ermöglicht den Zugriff auf die leistungsfähigeren ObjectContext-Klassenmitglieder aus Ihrem DbContext-Objekt.

// Get the key field name & value.
// This assumes your DbContext object is "_context", and that it is a single part key.
var e = ((IObjectContextAdapter)_context).ObjectContext.ObjectStateManager.GetObjectStateEntry(validationErrors.Entry.Entity);
string key = e.EntityKey.EntityKeyValues[0].Key;
string val = e.EntityKey.EntityKeyValues[0].Value;

Ich habe dasselbe Problem vor ein paar Tagen beim Aktualisieren der Datenbank konfrontiert. In meinem Fall gab es nur wenige neue nicht nullwertfähige Spalten, die für die Wartung hinzugefügt wurden, die nicht im Code enthalten waren, der die Ausnahme verursacht. Ich finde diese Felder heraus und gebe Werte für sie und ihre Lösung.


Ich habe diesen Fehler heute erhalten und konnte es eine Zeit lang nicht verarbeiten, aber ich merkte, dass es nach dem Hinzufügen einiger RequireAttribute s zu meinen Modellen war und dass einige Entwicklungsdaten nicht alle erforderlichen Felder RequireAttribute .
Wenn Sie diesen Fehler beim Aktualisieren der Datenbank durch eine Art von Init-Strategie wie DropCreateDatabaseIfModelChanges , müssen Sie sicherstellen, dass Ihre Seed-Daten alle Validierungsattribute für Modelldaten erfüllen und erfüllen .

Ich weiß, das ist etwas anders als das Problem in der Frage, aber es ist eine beliebte Frage, also dachte ich, ich würde ein bisschen mehr zur Antwort hinzufügen für andere, die dasselbe Problem haben wie ich.
Hoffe das hilft anderen :)


Sie können alle Informationen aus der DbEntityValidationException mit dem folgenden Code extrahieren (Sie müssen die Namespaces: System.Data.Entity.Validation und System.Diagnostics zu Ihrer using hinzufügen):

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);
        }
    }
}

Stellen Sie sicher, dass Sie, wenn Sie nvarchar (50) in der DB-Zeile haben, nicht versuchen, mehr als 50 Zeichen einzufügen. Dummer Fehler, aber dauerte 3 Stunden, um es herauszufinden.


Keine Codeänderung erforderlich:

Während Sie sich im Debug-Modus im catch {...} -Block befinden, öffnen Sie das "QuickWatch" -Fenster ( Strg + Alt + Q ) und fügen Sie dort ein:

((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors

oder:

((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors

Wenn Sie nicht versuchen / fangen oder keinen Zugriff auf das Ausnahmeobjekt haben.

Auf diese Weise können Sie einen Drilldown in die ValidationErrors Struktur durchführen. Es ist der einfachste Weg, den ich gefunden habe, um einen sofortigen Einblick in diese Fehler zu bekommen.







code-first