2011-03-06 22 views
6

Usted puede encontrar el código fuente que demuestra esta cuestión @http://code.google.com/p/contactsctp5/CTP5 EF Código primera pregunta

tengo tres objetos del modelo. Contacto, ContactInfo, ContactInfoType. Donde un contacto tiene muchas contactinfo y cada contactinfo es un tipo de contacto. Bastante simple, supongo. El problema que me estoy encontrando es cuando voy a editar el objeto de contacto. Lo saqué de mi repositorio de contactos. Luego ejecuto "UpdateModel (contacto);" y actualiza el objeto con todos los valores de mi formulario. (Monitoreo con depuración) Cuando guardo los cambios, sin embargo, me sale el siguiente error:

The operation failed: The relationship could not be changed because one or more of the foreign-key properties is non-nullable. When a change is made to a relationship, the related foreign-key property is set to a null value. If the foreign-key does not support null values, a new relationship must be defined, the foreign-key property must be assigned another non-null value, or the unrelated object must be deleted.

Parece que después de que yo llamo modelo de actualización que anula mis referencias y esto parece romper todo? Cualquier idea sobre cómo remediar sería muy apreciada. Gracias.

Éstos son mis modelos:

acción
public partial class Contact { 
    public Contact() { 
     this.ContactInformation = new HashSet<ContactInformation>(); 
    } 

    public int ContactId { get; set; } 
    public string FirstName { get; set; } 
    public string LastName { get; set; } 

    public virtual ICollection<ContactInformation> ContactInformation { get; set; } 
} 

public partial class ContactInformation { 
    public int ContactInformationId { get; set; } 
    public int ContactId { get; set; } 
    public int ContactInfoTypeId { get; set; } 
    public string Information { get; set; } 

    public virtual Contact Contact { get; set; } 
    public virtual ContactInfoType ContactInfoType { get; set; } 
    } 

    public partial class ContactInfoType { 
    public ContactInfoType() { 
     this.ContactInformation = new HashSet<ContactInformation>(); 
    } 

    public int ContactInfoTypeId { get; set; } 
    public string Type { get; set; } 

    public virtual ICollection<ContactInformation> ContactInformation { get; set; } 
    } 

Mi controlador:

[AcceptVerbs(HttpVerbs.Post)] 
    public ActionResult Edit(Contact person) { 
     if (this.ModelState.IsValid) { 
     var contact = this.contactRepository.GetById(person.ContactId); 
     UpdateModel(contact); 
     this.contactRepository.Save(); 
     TempData["message"] = "Contact Saved."; 
     return PartialView("Details", contact); 
     } else { 
     return PartialView(person); 
     } 
    } 

Código Contexto:

protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder) { 
     modelBuilder.Entity<Contact>() 
     .HasMany(c => c.ContactInformation) 
     .WithRequired() 
     .HasForeignKey(c => c.ContactId); 

     modelBuilder.Entity<ContactInfoType>() 
     .HasMany(c => c.ContactInformation) 
     .WithRequired() 
     .HasForeignKey(c => c.ContactInfoTypeId); 
    } 
+0

¿Es el error independiente del tipo de cambios que realiza en su formulario? Me imagino que tal error puede ocurrir si eliminas una 'ContactInformation' de la colección en' Contact'. ¿El error también ocurre si solo cambias, por ejemplo, el 'FirstName' en tu formulario y nada más? – Slauma

Respuesta

1

Me di cuenta de esta pregunta gracias a Morteza Manavi en el sitio web de la entidad marco. Mi problema fue causado por mis propiedades de modelo ContactInformation, 'contactid' & 'contacttypeid' no puede contener nulos. Una vez que arreglé esto, todo con UpdateModel() funcionó correctamente. ¡Muchas gracias!

3

Hay algunas cosas pasando aquí.

Si está configurado para la carga lenta, los objetos secundarios solo se cargan si les indica que carguen. Esto se puede hacer con lo siguiente en su consulta.

..

context.Contacts.Include(c => c.ContactInfos).Include(c => c.ContactInfos.ContactInfoType) 

ver this article para más detalles sobre cómo hacer objetos seguro que son cargados como desee.

Si no desea guardar la información de contacto y contactinfotype (porque no están cargados o simplemente no desea), tendrá que indicarle al contexto que no guarde los objetos secundarios que no deberían estar actualizado. Esto se puede hacer usando:

..

context.StateManager.ChangeObjectState(entity.ContactInfos.ContactInfoType, EntityState.Unchanged); 

Me parece que tengo que hacer que al cambiar/usando un objeto de país para datos de usuario. Definitivamente, nunca quiero que un usuario lo actualice.

En el medio de escribir un poco de una guía a todo esto, pero podría ser semanas hasta que se hace en mi blog

MVC no almacenará/enviar de vuelta cualquier cosa que no pone en la forma. Si envía una jerarquía de objetos a la forma y los valores no están representados en entradas ocultas, volverán vacíos en su modelo. Por esta razón, generalmente hago viewmodels que son solo editables versiones de las entidades con un ToEntity y un método ToModel en ellas. Esto también me cubre por seguridad ya que no quiero todo tipo de identificadores de usuario en entradas ocultas, solo para que mis entidades se asocien directamente a MVC (vea this article on overposting).

HABRÍA pensado que el hecho de que tenga sus propiedades de contactinfo configuradas como virtuales, al UpdateModel no le importaría si no existieran en la devolución, pero podría estar equivocado ya que no lo he probado.

+0

Mis propiedades contactinfo y contactinfotipo están marcadas como virtuales. Obtengo mi objeto de contacto del contexto, por un contexto simple.Contact.SingleOrDefault (c => c.ContactId == id); –

+0

OK, volví a leer mi respuesta y estaba un poco sesgada y ahora la edité. ¿Has intentado incluir explícitamente? Normalmente agrego un nivel de carga predeterminado en mis métodos GetQuery de repositorio. Se vería como el ejemplo en mi primer punto. Cambie su contexto.Contact.SingleOrDefault (c => c.ContactId == id) a context.Contact.Include (c => c.ContactInfos) .SingleOrDefault (c => c.ContactId == id) – Gats

+0

Intenté agregar el incluye, pero eso no cambió nada y sigo teniendo el mismo error. Todos los valores en el formulario se asignan correctamente a la variable de persona y todo se ve bien cuando se depura. Sin embargo, cuando preform el updatemodel() parece anular las referencias y cuando lo guardo, falla. –

Cuestiones relacionadas