Échec de la Validation pour une ou plusieurs entités lors de l'enregistrement de modifications à la base de données SQL Server en utilisant le cadre D'Entity
je veux sauver mon édition à la base de données et j'utilise le code de cadre D'entité-premier en ASP.NET MVC 3 / C# mais je reçois des erreurs. Dans ma classe D'événements, j'ai des types de données DateTime et TimeSpan, mais dans ma base de données, j'ai la Date et l'heure respectivement. Serait-ce la raison? Comment puis-je lancer vers le type de données approprié dans le code avant de sauvegarder les modifications dans la base de données.
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; }
}
méthode dans le contrôleur > > > > problème à storebd.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);
}
}
avec
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 Database /T-SQL
EventDate (Datatype = date)
StartTime (Datatype = time)
EndTime (Datatype = time)
Formulaire Http
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
erreur de serveur dans L'Application'/'.
Échec de la Validationpour une ou plusieurs entités. Voir la propriété "EntityValidationErrors" pour plus de détails.
Description: Une exception non gérée s'est produite pendant l'exécution de la demande web actuelle. Merci examinez la trace de la pile pour plus d'informations sur l'erreur et son origine dans le code.
Détails De L'Exception: Système.Données.Entité.Validation.DbEntityValidationException: la Validation a échoué pour une ou plusieurs entités. Voir la propriété "EntityValidationErrors" pour plus de détails.
Source D'Erreur:
Line 75: if (TryUpdateModel(theEvent))
Line 76: {
Line 77: storeDB.SaveChanges();
Line 78: return RedirectToAction("Index");
Line 79: }
Fichier Source: C:sepMvcEventCalendarMvcEventCalendarControllersEventManagerController.ligne cs: 77
Trace De La Pile:
[DbEntityValidationException: la Validation a échoué pour une ou plusieurs entités. Voir la propriété "EntityValidationErrors" pour plus de détails.]
16 réponses
vous pouvez extraire toutes les informations de la DbEntityValidationException
avec le code suivant (vous devez ajouter les espaces de noms: System.Data.Entity.Validation
et System.Diagnostics
à votre using
liste):
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);
}
}
}
aucun changement de code requis:
pendant que vous êtes en mode débogage dans le bloc catch {...}
ouvrez la fenêtre" QuickWatch " ( Ctrl + Alt + Q ) et collez là:
((System.Data.Entity.Validation.DbEntityValidationException)ex).EntityValidationErrors
ou:
((System.Data.Entity.Validation.DbEntityValidationException)$exception).EntityValidationErrors
si vous n'êtes pas dans un try/catch ou n'avez pas accès à l'objet exception.
cela vous permettra de creuser dans l'arbre ValidationErrors
. C'est le moyen le plus facile que j'ai trouvé pour avoir un aperçu instantané de ces erreurs.
dans le cas où vous avez des classes avec les mêmes noms de propriétés, voici une petite extension à la réponse de Praveen:
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);
}
}
}
pour améliorer à la fois Praveen et Tony, j'utilise un contrôleur:
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...
}
}
}
Cette mise en œuvre envelopper entité exception à l'exception du détail du texte.
Il manipule DbEntityValidationException
, DbUpdateException
, datetime2
les erreurs de gamme (MS SQL), et inclure la clé de l'entité invalide dans le message (utile quand savind beaucoup d'entités à un appel SaveChanges
).
premièrement, remplacer SaveChanges
dans la classe DbContext:
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 class:
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);
}
}
ce code a aidé à trouver mon problème lorsque j'ai eu des problèmes avec mes erreurs de VAlidation D'entité. Il m'a dit le problème exact avec ma définition D'entité. Essayez de suivre le code où vous devez couvrir storebd.SaveChanges(); dans la suite essayer bloc catch.
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;
}
j'ai eu cette erreur aujourd'hui et je n'ai pas pu le résoudre pendant un moment, mais j'ai réalisé que c'était après avoir ajouté quelques RequireAttribute
à mes modèles et que certaines données de développement de graine n'étaient pas peuplant tous les champs requis.
Donc juste une note que si vous obtenez cette erreur lors de la mise à jour de la base de données par une sorte de stratégie d'initialisation comme DropCreateDatabaseIfModelChanges
alors vous devez vous assurer que vos données de graine remplissent et satisfont des données de modèle attributs de validation .
je sais que c'est légèrement différent du problème dans la question, mais c'est une question populaire donc j'ai pensé que je voudrais ajouter un peu plus à la réponse pour les autres ayant le même problème que moi.
Espérons que cela aide les autres :)
je pense que l'ajout d'essayer / attraper pour chaque opération SaveChanges()
n'est pas une bonne pratique, il est préférable de centraliser ceci:
ajouter cette classe à la classe principale 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.ErrorMessage));
throw new DbEntityValidationException(errorMessages);
}
}
cela écrasera la méthode SaveChanges()
de votre contexte et vous obtiendrez une liste séparée par des virgules contenant toutes les erreurs de validation de l'entité.
cela peut également être amélioré, pour enregistrer les erreurs dans la production env, au lieu de jeter simplement un erreur.
j'espère que c'est utile.
voici une extension de L'extension de Tony... :- )
Pour Entity Framework 4.x, si vous voulez obtenir le nom et la valeur du champ clé pour que vous sachiez quelle instance de l'entité (enregistrement DB) a le problème, vous pouvez ajouter ce qui suit. Cela permet d'accéder aux membres les plus puissants de la classe ObjectContext à partir de votre objet DbContext.
// 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;
Je n'aime pas les exceptions J'ai enregistré les OnSaveChanges et j'ai ce
var validationErrors = model.GetValidationErrors();
var h = validationErrors.SelectMany(x => x.ValidationErrors
.Select(f => "Entity: "
+(x.Entry.Entity)
+ " : " + f.PropertyName
+ "->" + f.ErrorMessage));
Cette erreur se produit également lorsque vous essayez d'enregistrer une entité qui a des erreurs de validation. Un bon moyen de provoquer cela est d'oublier de vérifier ModelState.IsValid avant de sauvegarder dans votre base de données.
assurez-vous que si vous avez nvarchar(50)dans DB row vous n'essayez pas d'y insérer plus de 50 caractères. Erreur stupide mais ça m'a pris 3 heures pour le découvrir.
cela pourrait être dû au nombre maximum de caractères permis pour une colonne spécifique, comme dans sql un champ pourrait avoir le Type de données suivant nvarchar(5)
mais le nombre de caractères entrés par l'utilisateur est plus que le spécifié, donc l'erreur se produit.
j'ai fait face à la même question Il ya quelques jours lors de la mise à jour de la base de données. Dans mon cas, il y a eu peu de nouvelles colonnes non nulles ajoutées pour la maintenance qui n'ont pas été fournies dans le code qui est à l'origine de l'exception. Je trouve ces champs et ai fourni des valeurs pour eux et son résolu.
Merci pour vos réponses, ça m'aide beaucoup. comme je code dans Vb.Net, ce code de Vb.Net
Try
Return MyBase.SaveChanges()
Catch dbEx As Validation.DbEntityValidationException
For Each [error] In From validationErrors In dbEx.EntityValidationErrors
From validationError In validationErrors.ValidationErrors
Select New With { .PropertyName = validationError.PropertyName,
.ErrorMessage = validationError.ErrorMessage,
.ClassFullName = validationErrors.Entry.Entity
.GetType().FullName}
Diagnostics.Trace.TraceInformation("Class: {0}, Property: {1}, Error: {2}",
[error].ClassFullName,
[error].PropertyName,
[error].ErrorMessage)
Next
Throw
End Try
il peut être causé par une propriété qui n'est pas peuplée par model.. au lieu de cela, il est peuplé par Controller.. ce qui peut provoquer cette erreur.. la solution à cela est d'attribuer la propriété avant d'appliquer ModelState de validation. et cette seconde Hypothèse . vous avez déjà des Données dans votre Base de données et en essayant de le mettre à jour, mais aujourd'hui, l'extraction.