2011-08-18 21 views
6

Estoy solucionando el problema con la actualización de la entidad antes de guardarla en la base de datos y obtuve un comportamiento extraño.Extraña actualización de entidad en Entity Framework Code-First

Estoy usando Entity Framework 4.1 Code-First en la aplicación web ASP.NET MVC 3. Aquí está el modelo:

public class Order 
{ 
    public int OrderId { get; set; } 
    public int CarId { get; set; } 
    public DateTime BeginRentDate { get; set; } 
    public DateTime EndRentDate { get; set; } 
    public decimal RentPrice { get; set; } 
    public virtual Car Car { get; set; } 
} 

public class Car 
{ 
    public int CarId { get; set; } 
    public string Brand { get; set; } 
    public string Model { get; set; } 
    public string NumberPlate { get; set; } 
    public decimal RentPrice { get; set; } 
} 

Cada coche tiene un precio de alquiler. Este precio debe copiarse en RentPrice de Order al crear uno. El coche es la selección por el usuario por lo que inicialmente Order.RentPrice es 0.

Aquí quiero copiar valor del precio:

[HttpPost] 
public ActionResult Create(Order order) 
{ 
    order.RentPrice = _context.Cars.Find(order.CarId).RentPrice; 

    if (ModelState.IsValid) 
    { 
     _context.Orders.Add(order); 
     _context.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 

    return View(order); 
} 

No está funcionando debido a un error en la SaveChanges esa entidad tiene errores de validación. DE ACUERDO. Descubrí que primero es necesario llamar al UpdateModel(order); y luego cambiar los valores.

Así que lo que tengo. el código de trabajo:

_context.Orders.Add(order); 
UpdateModel(order); 
order.RentPrice = 777; 
_context.SaveChanges(); 

No código de trabajo:

_context.Orders.Add(order); 
UpdateModel(order); 
order.RentPrice = _context.Cars.Find(order.CarId).RentPrice; 
_context.SaveChanges(); 

código de trabajo (!):

_context.Orders.Add(order); 
UpdateModel(order); 
var t = (double)_context.Cars.Find(order.CarId).RentPrice; 
order.RentPrice = (decimal)t; 
_context.SaveChanges(); 

¿Puede alguien explicar, por favor, ¿qué está pasando aquí? Especialmente magia en la 3ª y 4ª líneas en el último bloque de código.

actualización

Me estoy DbEntityValidationException: "Error en la validación de una o más entidades Ver propiedad '' EntityValidationErrors para más detalles.". De la excepción interna: "OriginalValues ​​no se puede usar para entidades en el estado Agregado".

+1

Notaste que tenías dos puntos y comas al final de la orden.RentPrice = _context.Cars.Find (order.CarId) .RentPrice ;; -> en el siguiente al último bloque de código? – Jack

+1

¿Cuáles son los errores de validación en el método SaveChanges? El código en su método Create inicial funciona bien para mí. – agradl

+0

@Jack, solo un error tipográfico al escribir una publicación. Fijo. –

Respuesta

0

¿Ha declarado la clave primaria en algún lugar? Usted debe hacer que, o bien utilizando FluentAPI o atributo de esta manera:

public class Order 
{ 
    [Key] 
    public int OrderId { get; set; } 
    public int CarId { get; set; } 
    public DateTime BeginRentDate { get; set; } 
    public DateTime EndRentDate { get; set; } 
    public decimal RentPrice { get; set; } 
    public virtual Car Car { get; set; } 
} 

public class Car 
{ 
    [Key] 
    public int CarId { get; set; } 
    public string Brand { get; set; } 
    public string Model { get; set; } 
    public string NumberPlate { get; set; } 
    public decimal RentPrice { get; set; } 
} 

o en su contexto, puede utilizar la API de Fluido para declarar la clave, como este

builder.Entity<Car>().HasKey(x=>x.CarId); 
builder.Entity<Order>().HasKey(x=>x.OrderId); 
+0

EF usa la convención sobre la configuración (toma la propiedad de Id para esto). Entonces, sí, mi base de datos tiene claves principales. Lo comprobé. ¿Y cómo se explica el último bloque de código? ... –

0

Tengo una idea, pero es más de una suposición ... ¿Tal vez para cuando ingresas a esa función de Crear, el contexto ya sabe de esa Orden? Si lo hace, intentar volver a agregarlo podría generar ese error.

En su último fragmento de código (el que sorprendentemente funciona), ¿ha tratado de usar una var intermediaria sin fundición para duplicar?

También me intriga ese UpdateModel ... Utilizo EF pero no MVC, así que quizás no tenga nada que ver al respecto, pero si se trata de una función personalizada, ¿qué hace?

18

Al llegar

"Error en la validación de una o más entidades. Ver propiedad 'EntityValidationErrors' para más detalles."Desde el interior excepción: 'OriginalValues ​​no se pueden utilizar para las entidades en el estado Agregado '

Se significa que hubo errores como collumns NO NULL que eran las limitaciones en blanco o de otro tipo, compruebe los errores de validación entidad por. depuración o como

try{ 
... 
catch (DbEntityValidationException ex) 
    { 
foreach (var validationErrors in ex.EntityValidationErrors) 
    { 
    foreach (var validationError in validationErrors.ValidationErrors) 
    { 
     System.Diagnostics.Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); 
    } 
    } 
} 
+0

¿Has leído los ejemplos de mi código en la pregunta? –

+0

Disculpe, no tengo una explicación para su pregunta original solo un consejo de cómo obtener el error realmente de esa DbEntityValidationException – John

+0

En mi caso, encontré una anotación de datos no coincidentes entre mi modelo de vista de registro y mi modelo de identidad. – Dreamcasting

0

estoy seguro de que el problema se habría corregido hace mucho tiempo, sólo quería contribuir con mis 2 centavos.

también me encontré con un problema con el mismo mensaje de error, yo estaba usando Oracle y EF 5.0. Fin Aliado obtuve una solución después de perder más de 12 horas.

Para mí fue la falta de permisos para el usuario en la tabla donde estaba tratando de insertar valores y el mensaje de error no tenía ninguna pista sobre el problema de permiso real, lo cual era realmente extraño.

Espero que alguien lo encuentre útil y no pierda horas como yo en la solución de problemas.

Saludos,

Avi

1

OriginalValues ​​no se pueden utilizar para las entidades en el Estado agregó.

pueden ser corregidos por asegurar que no identidad campos de clave principal se especifican como no generada en el modelo.

modelBuilder 
    .Entity<T>() 
    .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 
    // this can also be achieved using attributes on the entity. 

El error es en realidad explica por sí mismo cuando se tiene contexto, pero desconcertante lo contrario. La base de datos genera dos instrucciones a la inserción, la segunda de las cuales es:

SELECT [PrimaryKeyId] 
FROM [dbo].[Entity] 
WHERE @@ROWCOUNT > 0 AND [PrimaryKeyId] = scope_identity() 
/* SP:StmtCompleted... */ 

Esta declaración no devuelve ninguna fila para no identidad columnas. Por lo tanto, el OriginalValues permanecerá inalterado en el estado agregado. Esto también explica por qué esta excepción se envuelve en un OptimisticConcurrencyException ya que el número de filas afectadas se usa para detectar datos alterados existentes.

Cuestiones relacionadas