asp.net-mvc-3 - tutorial - update database entity framework code first
Primer código EF: ¿Cómo veo la propiedad ''EntityValidationErrors'' de la consola del paquete nuget? (6)
Convertí la respuesta de Richards a un método de extensión:
public static int SaveChangesWithErrors(this DbContext context)
{
try
{
return context.SaveChanges();
}
catch (DbEntityValidationException ex)
{
StringBuilder sb = new StringBuilder();
foreach (var failure in ex.EntityValidationErrors)
{
sb.AppendFormat("{0} failed validation/n", failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors)
{
sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
sb.AppendLine();
}
}
throw new DbEntityValidationException(
"Entity Validation Failed - errors follow:/n" +
sb.ToString(), ex
); // Add the original exception as the innerException
}
}
Llamar así:
context.SaveChangesWithErrors();
Estoy perdido por esto:
Definí mis clases para el primer enfoque del código entidad marco (4.1.3). Todo estaba bien (estaba creando las tablas, etc.) hasta que comencé a Seed.
Ahora cuando hago el
Add-Migration "remigrate" ; Update-Database;
Aparece un error en la consola del paquete "La validación falló para una o más entidades. Consulte la propiedad ''EntityValidationErrors'' para obtener más detalles".
Tengo un punto de interrupción en mi método Seed () pero debido a que estoy ejecutando esto en la consola cuando el proyecto no se está ejecutando, no tengo ni idea de cómo llegar a los detalles (PD: he visto que la validación de la secuencia falló para una o más entidades al guardar los cambios en la base de datos de SQL Server utilizando Entity Framework que muestra cómo puedo ver la propiedad).
Sé que mi método Seed () tiene un problema porque si pongo una devolución justo después de la llamada al método, el error desaparece. Entonces, ¿cómo configuro mi punto de interrupción para poder ver cuál es el error de validación? Un poco perdido ¿O hay alguna otra forma de rastrearlo en la consola nuget?
Convertí la versión de Craigvl a C #. Tuve que agregar context.SaveChanges (); para que funcione para mí como a continuación.
try
{
byte[] bytes = System.IO.File.ReadAllBytes(@"C:/Users/sheph_000/Desktop/Rawr.png");
Console.WriteLine(bytes);
context.BeverageTypes.AddOrUpdate(
x => x.Name,
new AATPos.DAL.Entities.BeverageType { ID = 1, Name = "Sodas" }
);
context.Beverages.AddOrUpdate(
x => x.Name,
new AATPos.DAL.Entities.Beverage { ID = 1, Name = "Coke", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
new AATPos.DAL.Entities.Beverage { ID = 2, Name = "Fanta", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
new AATPos.DAL.Entities.Beverage { ID = 3, Name = "Sprite", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
new AATPos.DAL.Entities.Beverage { ID = 4, Name = "Cream Soda", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" },
new AATPos.DAL.Entities.Beverage { ID = 5, Name = "Pepsi", BeverageTypeID = 1, ImageData = bytes, IsStocked = true, StockLevel = 10, Price = 10.00M, ImageMimeType = "test" }
);
context.SaveChanges();
}
catch (System.Data.Entity.Validation.DbEntityValidationException ex)
{
var sb = new System.Text.StringBuilder();
foreach (var failure in ex.EntityValidationErrors)
{
sb.AppendFormat("{0} failed validation", failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors)
{
sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
sb.AppendLine();
}
}
throw new Exception(sb.ToString());
}
Me molesté por esto recientemente también. Lo arreglé poniendo una función de envoltura en la clase de Configuración en el método de Seed, y reemplacé las llamadas a SaveChanges
con las llamadas a mi función en su lugar. Esta función simplemente enumeraría los errores dentro de la colección EntityValidationErrors
y EntityValidationErrors
lanzar una excepción donde el mensaje de excepción enumera los problemas individuales. Esto hace que la salida aparezca en la consola del administrador de paquetes NuGet.
El código sigue:
/// <summary>
/// Wrapper for SaveChanges adding the Validation Messages to the generated exception
/// </summary>
/// <param name="context">The context.</param>
private void SaveChanges(DbContext context) {
try {
context.SaveChanges();
} catch (DbEntityValidationException ex) {
StringBuilder sb = new StringBuilder();
foreach (var failure in ex.EntityValidationErrors) {
sb.AppendFormat("{0} failed validation/n", failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors) {
sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
sb.AppendLine();
}
}
throw new DbEntityValidationException(
"Entity Validation Failed - errors follow:/n" +
sb.ToString(), ex
); // Add the original exception as the innerException
}
}
Simplemente reemplace las llamadas a context.SaveChanges()
con SaveChanges(context)
en su método de SaveChanges(context)
.
Richard, gracias por ponerme en el camino correcto (tenía el mismo problema) a continuación, hay una alternativa sin el envoltorio que funcionó para mí en el método de configuración de la migración:
Protected Overrides Sub Seed(context As NotificationContext)
Try
context.System.AddOrUpdate(
Function(c) c.SystemName,
New E_NotificationSystem() With {.SystemName = "System1"},
New E_NotificationSystem() With {.SystemName = "System2"},
New E_NotificationSystem() With {.SystemName = "System3"})
context.SaveChanges()
Catch ex As DbEntityValidationException
Dim sb As New StringBuilder
For Each failure In ex.EntityValidationErrors
sb.AppendFormat("{0} failed validation" & vbLf, failure.Entry.Entity.[GetType]())
For Each [error] In failure.ValidationErrors
sb.AppendFormat("- {0} : {1}", [error].PropertyName, [error].ErrorMessage)
sb.AppendLine()
Next
Next
Throw New Exception(sb.ToString())
End Try
End Sub
Pudo ver la excepción en la consola del administrador de paquetes. Espero que esto ayude a alguien.
¡Extienda su clase DBContext ya con una definición de clase parcial!
Si miras la definición de clase para tu DbContext, será algo como lo siguiente:
// DatabaseContext.cs -- This file is auto generated and thus shouldn''t be changed.
public partial class [DatabaseContextName] : DbContext { ... }
Por lo tanto, en otro archivo puede crear la misma definición y anular las partes que desee.
// partialDatabaseContext.cs -- you can safely make changes
// that will not be overwritten in here.
public partial class [DatabaseContextName] : DbContext { // Override defaults here }
Toda la idea con clases parciales, notó que DbContext es una clase parcial, es que puede extender una clase que se ha generado (u organizar clases en múltiples archivos) y en nuestro caso también queremos anular el método SaveChanges desde dentro de una clase parcial que se agrega al DbContext .
De esta forma, podemos obtener información de depuración de errores de todas las llamadas existentes de DbContext / SaveChanges en cualquier lugar y no tener que cambiar el código de semilla o el código de desarrollo.
Esto es lo que haría ( TENGA EN CUENTA que la diferencia es que simplemente anulo el método SaveChanges en nuestra propia clase parcial autorizada DbContext , NO LA GENERADA ). Además, asegúrese de que la clase parcial use el espacio de nombres correcto o golpeará su cabeza contra la pared.
public partial class Database : DbContext
{
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (DbEntityValidationException ex)
{
var sb = new StringBuilder();
foreach (var failure in ex.EntityValidationErrors)
{
sb.AppendFormat("{0} failed validation/n", failure.Entry.Entity.GetType());
foreach (var error in failure.ValidationErrors)
{
sb.AppendFormat("- {0} : {1}", error.PropertyName, error.ErrorMessage);
sb.AppendLine();
}
}
throw new DbEntityValidationException(
"Entity Validation Failed - errors follow:/n" +
sb.ToString(), ex
); // Add the original exception as the innerException
}
}
}
I Also had same model validation problem but successfully catch by myself after lot of thinking;
I use reverse engineering method to catch the problem out of Over 80 + Model Classes;
1> Made copy of dbcontext, changing the name (I add "1" at end and make respective changes in class constructor and initialization etc.
Old:
>public class AppDb : IdentityDbContext<ApplicationUser>
>
> {
> public AppDb(): base("DefaultConnection", throwIfV1Schema: false)
> {
>
> }
>
> public static AppDb Create()
>{
>return new AppDb();
>}
**New:**
>public class AppDb1 : IdentityDbContext<ApplicationUser>
>{
>public AppDb1()
>: base("DefaultConnection", throwIfV1Schema: false)
>{
>}
>
>public static AppDb1 Create()
> {
> return new AppDb1();
> }`
...
2> Make changes to Codefirst Migration Configuration from Old DbContext to my new Context.
> internal sealed class Configuration :
> DbMigrationsConfiguration<DAL.AppDb1> { public Configuration() {
> AutomaticMigrationsEnabled = false; } protected override void
> Seed(DAL.AppDb1 context) {`
3> Comment the Dbsets in new DbContext which was doubt.
4> Apply update migration if succeeded the probelm lye in Commented section.
5> if not then commented section is clear of bug clear.
6> repeat the (4) until found the right place of bug.
7> Happy Codding