7

Ho i due seguenti modelli e DbContext:Entity Framework - Aggiornamento rapporto modificando estera chiave

public class TestDbContext : DbContext 
    { 
     public IDbSet<Person> People { get; set; } 
     public IDbSet<Car> Cars { get; set; } 
    } 

    public class Person 
    { 
     public Person() 
     { 
      ID = Guid.NewGuid(); 
     } 

     public Guid ID { get; set; } 
     public string Name { get; set; } 
     public virtual List<Car> Cars { get; set; } 
    } 

    public class Car 
    { 
     public Car() 
     { 
      ID = Guid.NewGuid(); 
     } 

     public Guid ID { get; set; } 
     public string Name { get; set; } 
     public virtual Person Owner { get; set; } 
    } 

ho quindi dichiarare una lista di persone e un elenco di vetture, impostare il proprietario della prima auto al prima persona nella lista:

List<Person> People = new List<Person>() 
     { 
      new Person() {Name = "bill", ID = new Guid("6F39CC2B-1A09-4E27-B803-1304AFDB23E3")}, 
      new Person() {Name = "ben", ID = new Guid("3EAE0303-39D9-4FD9-AF39-EC6DC73F630B")} 
     }; 

     List<Car> Cars = new List<Car>() { new Car() { Name = "Ford", Owner = People[0], ID = new Guid("625FAB6B-1D56-4F57-8C98-F9346F1BBBE4") } }; 

L'ho salvato nel database utilizzando il seguente codice e funziona correttamente.

using (TestDbContext context = new TestDbContext()) 
     { 
      foreach (Person person in People) 
      { 
       if (!(context.People.Any(p => p.ID == person.ID))) 
        context.People.Add(person); 
       else 
       { 
        context.People.Attach(person); 
        context.Entry<Person>(person).State = System.Data.EntityState.Modified; 
       } 
      } 
      foreach (Car caar in Cars) 
      { 
       if (!(context.Cars.Any(c => c.ID == caar.ID))) 
        context.Cars.Add(caar); 
       else 
       { 
        context.Cars.Attach(caar); 
        context.Entry<Car>(caar).State = System.Data.EntityState.Modified; 
       } 
      } 
      context.SaveChanges(); 
     } 

Se poi cambiare il proprietario della vettura per la seconda persona ed eseguire di nuovo il codice, la proprietà Auto proprietario non si aggiorna.

Cars[0].Owner = People[1]; 

Qualche idea su cosa sto facendo male? Grazie per qualsiasi aiuto.

+0

Solo per aggiungere, sto cercando di ottenere ciò che è suggerito http://stackoverflow.com/questions/9382005/move-child-entities-to-a-new-parent-entity – user2697817

+0

Come lo hai salvato? Dov'è il codice per questo? È necessario ricaricare 'Cars' dal DB e quindi eseguire il compito. – zsong

risposta

2

Credo che questo sia un problema di independent vs foreign key association. Al momento stai usando un'associazione indipendente e la relazione tra auto e persona è effettivamente gestita da un oggetto entry separato che ha il suo stato (per accedere a questo oggetto devi utilizzare l'API ObjectContext). L'impostazione della voce dell'entità dell'auto in stato modificato non cambierà lo stato della voce per la relazione! La soluzione più semplice è utilizzare invece l'associazione di chiavi esterne, il che significa aggiungere una nuova proprietà Guid PersonId alla tua auto e mapparla come proprietà di chiave esterna per la proprietà di navigazione Person.

Se si insiste sull'utilizzo di associazioni indipendenti, è necessario modificare le relazioni solo su entità collegate altrimenti si avrà un forte mal di testa con il monitoraggio di tali modifiche e l'impostazione di tutte le voci richieste con lo stato corretto. Dovrebbe essere sufficiente per creare oggetti, collegarli al contesto e solo dopo aver impostato il proprietario dell'auto, si spera che venga tracciato come una modifica.

+0

Grazie per il tuo aiuto, è simile a fare ciò che è suggerito in questa risposta http: // StackOverflow.it/questions/5506116/entity-framework-code-first-why-cant-i-update-complex-properties-this-way – user2697817

+0

Sì, dovrebbe essere lo stesso. –

+0

@LadislavMrnka: Solo nota a parte: ho davvero rispetto per te e apprezzo il tuo contributo qui a molte domande su EF ... potresti per favore controllare anche la mia domanda? http://stackoverflow.com/questions/18529338/entity-framework-controlling-db-connection-and-specifying-own-transaction – Learner

0

provare qualcosa di simile:

using (TestDbContext context = new TestDbContext()) 
      { 
       foreach (Person person in People) 
       { 
        if (!(context.People.Any(p => p.ID == person.ID))) 
         context.People.Add(person); 
        else 
        { 
         context.People.Attach(person); 
         context.Entry<Person>(person).State = System.Data.EntityState.Modified; 
        } 
        context.SaveChanges(); 
       } 
       foreach (Car caar in Cars) 
       { 
        if (!(context.Cars.Any(c => c.ID == caar.ID))) 
         context.Cars.Add(caar); 
        else 
        { 
         context.Cars.Attach(caar); 
         context.Entry<Car>(caar).State = System.Data.EntityState.Modified; 
        } 
        context.SaveChanges(); 
       } 

      } 

penso che l'errore è dovuto alle context.SaveChanges collocamenti (e partialy vostra architettura). Potresti utilizzare un metodo dedicato (ad esempio un CRUD di base) per ogni operazione sul tuo DB tramite Entity Framework. Spero che questo ti aiuti.

Edit: Con un'approch CRUD:

public class PersonManager // CRUD 
    { 
     public void Create(Person person) 
     { 
      using (TestDbContext context = new TestDbContext()) 
      { 
       context.Person.Add(person); 
       context.SaveChanges(); 
      } 
     } 

     public void Update(Person person) 
     { 
      using (TestDbContext context = new TestDbContext()) 
      { 
       context.Person.Attach(person); 
       context.Entry(person).State = System.Data.EntityState.Modified; 
       context.SaveChanges(); 
      } 
     } 
    } 

Si potrebbe anche fare questa classe static al fine di adattarsi alla propria architettura.

+0

Ho provato questo approccio e non funziona ancora. – user2697817

+0

Hai appena copiato/incollato? O hai creato un CRUD di base? Perché con un approccio CRUD non dovresti avere errori ... – Atlasmaybe

+0

Ho provato quello che mi hai suggerito, non ha funzionato. Forse hai bisogno di essere più chiaro. :-) – user2697817

Problemi correlati