2012-01-13 31 views
6

Estoy tratando de actualizar un modelo complejo en una sola vista. estoy usando ASP.NET MVC3, Marco de la entidad con el código en primer lugar, unidad de trabajo, patrón de repositorio genérico .. pero cuando trato de actualizar el modelo, se me ocurre este error:Cómo actualizar el modelo complejo en ASP.NET MVC 3

Una restricción de integridad referencial se produjo una infracción: los valores de las propiedades que definen las restricciones referenciales no son consistentes entre los objetos principales y dependientes en la relación.

Aquí es mi modelo de vista simplificada:

public class TransactionViewModel 
{ 
    public Transaction Transaction { get; set; } 
    public bool IsUserSubmitting { get; set; } 
    public IEnumerable<SelectListItem> ContractTypes { get; set; } 
} 

Aquí está mi complejo modelo simplificado, y como ejemplo uno de su propiedad de navegación. Transacción tiene relación uno a uno con todas sus propiedades de navegación:

public class Transaction 
{ 
    [Key] 
    public int Id { get; set; } 

    public int CurrentStageId { get; set; } 

    public int? BidId { get; set; } 

    public int? EvaluationId { get; set; } 

    public virtual Stage CurrentStage { get; set; } 

    public virtual Bid Bid { get; set; } 

    public virtual Evaluation Evaluation { get; set; } 

} 

public class Bid 
{ 
    [Key] 
    public int Id { get; set; } 

    public string Type { get; set; } 

    public DateTime? PublicationDate { get; set; } 

    public DateTime? BidOpeningDate { get; set; } 

    public DateTime? ServiceDate { get; set; } 

    public string ContractBuyerComments { get; set; } 

    public string BidNumber { get; set; } 

    public DateTime? ReminderDate { get; set; } 

    public DateTime? SubmitDate { get; set; } 

} 

Utilizando el mismo modelo de vista, yo soy capaz de crear un objeto de transacción, lo que poblar la base de datos como este.

Id: 1, CurrentStageId: 1, BidId: 1, EvaluationId: 1

pero, cuando intento para actualizar las propiedades dentro de estas propiedades de navegación, esta línea hace que el error, en el controlador:

[HttpPost] 
public ActionResult Edit(TransactionViewModel model) 
{ 
    if (ModelState.IsValid) 
    { 
     -> unitOfWork.TransactionRepository.Update(model.Transaction); 
      unitOfWork.Save(); 
      return RedirectToAction("List"); 
    } 
} 

En repositorio genérico:

public virtual void Update(TEntity entityToUpdate) 
{ 
-> dbSet.Attach(entityToUpdate); 
    context.Entry(entityToUpdate).State = EntityState.Modified; 
} 

El problema se complica aún más porque debería ser capaz de modificar cualquiera de los campos (propiedades) dentro de cualquiera de las propiedades de navegación dentro del objeto Transaction dentro de una vista única.

Respuesta

12

creo que la excepción significa lo siguiente:

Los valores de las propiedades que definen las restricciones de referencia ... (estos son la propiedad de clave principal (= Id) valor de Bid y la propiedad de clave externa (= BidId) valor de Transaction)

... no son consistentes ... (= tener valores diferentes)

... entre el principal ... (= Bid)

... y dependiente ... (= Transaction)

... objetos en la relación.

Por lo tanto, se ve como la siguiente: Cuando el aglutinante modelo MVC crea la TransactionViewModel como parámetro para la acción Edit, model.Transaction.BidId y model.Transaction.Bid.Id son diferentes, por ejemplo:

  • model.Transaction.BidId.HasValue es true pero model.Transaction.Bid es null
  • model.Transaction.BidId.HasValue es false pero no es model.Transaction.Bidnull
  • model.Transaction.BidId.Value! = model.Transaction.Bid.Id

(El primer punto es, probablemente, no un problema. Supongo que tiene una situación 2.)

Lo mismo se aplica a CurrentStage y Evaluation.

soluciones posibles:

  • fijar esas propiedades a los mismos valores antes de llamar al método de su repositorio Update (= piratear)
  • Bind TransactionViewModel.Transaction.BidId y TransactionViewModel.Transaction.Bid.Id a dos campos de formulario ocultos con el mismo valor, de modo que el archivador modelo llena ambas propiedades.
  • Utilice también un ViewModel para su propiedad interior Transaction (y para las propiedades de navegación dentro de Transaction también) que se adapta a su vista y que puede asignar adecuadamente a las entidades en su acción de controlador.

Un último punto a mencionar es que esta línea ...

context.Entry(entityToUpdate).State = EntityState.Modified; 

... no marca los objetos relacionados (Transaction.Bid), modificadas, por lo que no sería guardar los cambios de Transaction.Bid. También debe establecer el estado de los objetos relacionados en Modified.

Nota al margen: Si no tiene ningún mapeo adicional con la API Fluent para EF, todas sus relaciones no son individuales sino de una a varias porque tiene propiedades FK separadas. Las relaciones uno-a-uno con EF requieren claves primarias compartidas.

+1

¡Estabas exactamente en lo cierto! El uso de claves primarias compartidas para la relación uno-a-uno y la configuración manual de las ID en el controlador resolvió el problema. ¡Gracias! – ljustin

+0

Estaba experimentando un problema similar en el que había escrito una clase de repositorio base genérica que todos los demás repositorios podrían implementar. Asegurándome de que solo las ID de las entidades relacionadas se usaran en lugar de toda la entidad relacionada, resolvió mi problema. – Garry

+0

joonho, estoy teniendo el problema. ¿Puedes ayudarnos a configurar los valores manualmente en los controladores por favor? – mmssaann