2011-07-19 6 views
5

estoy usando EF 4,1 código primero con SQL CE 4.0EF 4,1 código-I dC SQL 4.0 actualización de la colección excepción

que tienen dos clases

public class Customer 
{ 
    public int ID { get; set; } 

    public string CompanyName { get; set; } 

    public List<ContactPerson> ContactPersons { get; set; } 
} 

public class ContactPerson 
{ 
    public int ID { get; set; } 

    public string Name { get; set; } 

} 

y una DbContext

public class MyDB : DbContext 
{ 
    public DbSet<ContactPerson> ContactPersons { get; set; } 

    public DbSet<Customer> Customers { get; set; } 

    public MyDB() 
    { 
     this.Configuration.LazyLoadingEnabled = true; 
    } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Customer>() 
      .HasMany(c => c.ContactPersons) 
      .WithRequired() 
      .WillCascadeOnDelete(true); 
    } 
} 

Al mismo tiempo en el código, necesito actualizar toda la colección de ContactPerson de un cliente.

List<ContactPersons> modifiedContactPersons; 
Customer customer = MyDB.Customers.Find(ID); 
customer.ContactPersons = modifiedContactPersons; 

cuando me llaman MyDB.SaveChanges() me sale el siguiente excepción:

Se ha producido un error al guardar las entidades que no expongan extranjeros clave propiedades de sus relaciones. La propiedad EntityEntries será return null porque no se puede identificar una sola entidad como fuente de la excepción. El manejo de excepciones mientras se guarda puede hacerse más fácil al al exponer propiedades de clave foránea en sus tipos de entidad. Vea la InnerException para más detalles.

con InnerException:

Una relación de AssociationSet los 'Customer_ContactPersons' está en el estado 'Borrada'. Dadas las restricciones de multiplicidad, un correspondiente 'Customer_ContactPersons_Target' también debe estar en estado 'Eliminado'.

Entiendo lo que esto implica pero no puedo resolver el problema yo solo. ¿Alguna sugerencia?

Respuesta

8

El problema aquí es la siguiente:

customer.ContactPersons = modifiedContactPersons; 

Sustituye lista de viejas personas de contacto relacionados con la lista de nuevas personas de contacto relacionado y lo hace dos operaciones:

  • Es primera relación marca a todos personas previamente relacionadas con Deleted
  • A continuación, adjuntar a todas las personas nuevas de contrato y marcar la relación con ellos como Added

La primera operación es un problema porque eliminar la relación no elimina la entidad relacionada, por lo que termina con ContactPerson que no está relacionado con ningún Customer y su mapeo no lo permite (FK no puede contener nulos).

Resolver este problema depende del requisito que se intenta lograr. Si realmente desea eliminar primero a todas las personas relacionadas, debe establecer el estado de cada una para eliminarlas manualmente antes de asignar una nueva lista. Si desea actualizar personas existentes, no debe hacer esto en absoluto. Debe repetir las personas relacionadas con el cliente y modificar sus datos de una nueva lista. ¿Por qué?Porque:

  • Si elimina entidad e insertar uno nuevo en lugar de actualizar uno ya existente, tendrá dos instrucciones de modificación de la base de datos en lugar de uno = dos de ida y vuelta a la base de datos en lugar de uno, y en el caso de muchas entidades que se ralentizará su solicitud mucho
  • Si tiene alguna otra entidad dependiente de ContractPerson no puede eliminarla. Además, si utiliza el ContractPersonId en algún lugar, y si se genera automáticamente, ya no existirá después de eliminar el registro original.
  • En general, es un enfoque terriblemente incorrecto y perezoso. Inserte nuevos registros, modifique los registros existentes y elimine solo los registros que realmente deberían eliminarse.
+0

Escribe: "Debe repetir las personas relacionadas con el cliente y modificar sus datos de una nueva lista". ¿Cómo hago eso de la manera más simple? – esba

Cuestiones relacionadas