2010-08-29 12 views
10

il mio codice è qualcosa di simile:come aggiornare un'entità in Entity Framework 4 .NET

public class Program 
{ 
[STAThread] 
static void main() 
{ 
    DataAccessClass dal = new DataAccessClass(); 
    List<Person> list = dal.GetPersons(); 
    Person p = list[0]; 
    p.LastName = "Changed!"; 
    dal.Update(p); 
} 
} 

public class DataAccessClass 
{ 
public static List<Person> GetPersons() 
{ 
    MyDBEntities context = new MyDBEntities(); 
    return context.Persons.ToList(); 
} 

public void Update(Person p) 
{ 
    // what sould be written here? 
} 
} 

ora la prego di dirmi cosa devo scrivere nel metodo Update()? tutto ciò che scrivo, incontra varie eccezioni. (fare attenzione che i dati caricati siano tracciati, collegati o qualcosa del genere)

risposta

19

Il problema è che le entità Persona sono ancora collegate al contesto creato in GetPersons. Se si desidera lavorare con entità collegate, è necessario utilizzare la stessa istanza di contesto sia nelle operazioni di selezione che di aggiornamento. Hai due opzioni per risolvere il tuo problema.

1) Le persone collegate correttamente gestite

public class Program 
{ 
    [STAThread] 
    static void main() 
    { 
    using (DataAccessClass dal = new DataAccessClass()) 
    { 
     List<Person> list = dal.GetPersons(); 
     Person p = list[0]; 
     p.LastName = "Changed!"; 
     dal.Save(); 
    } 
    } 
} 

public class DataAccessClass : IDisposable 
{ 
    private MyDBEntities _context = new MyDBEntities(); 

    public List<Person> GetPersons() 
    { 
    return _context.Persons.ToList(); 
    } 

    public void Save() 
    { 
    // Context tracks changes on your entities. You don't have to do anything. Simply call 
    // SaveChanges and all changes in all loaded entities will be done in DB. 
    _context.SaveChanges(); 
    } 

    public void Dispose() 
    { 
    if (_context != null) 
    { 
     _context.Dispose(); 
     _context = null; 
    } 
    } 
} 

2) Non usare le entità collegate

public class Program 
{ 
    [STAThread] 
    static void main() 
    { 
    DataAccessClass dal = new DataAccessClass()) 
    List<Person> list = DataAccessClass.GetPersons(); 
    Person p = list[0]; 
    p.LastName = "Changed!"; 
    dal.Update(p); 
    } 
} 

public class DataAccessClass 
{ 
    public static List<Person> GetPersons() 
    { 
    // Closing context will detach entities 
    using (MyDBEntities context = new MyDBEntities()) 
    { 
     return context.Persons.ToList(); 
    } 
    } 

    public void Update(Person p) 
    { 
    using (MyDBEntities context = new MyDBEntities()) 
    { 
     context.Persons.Attach(p); 
     // Detached entities don't track changes so after attaching you have to say 
     // what changes have been done 
     context.ObjectStateManager.ChangeObjectState(p, System.Data.EntityState.Modified); 
     context.SaveChanges(); 
    } 
    } 
} 
+0

La ringrazio molto 'Ladislav Mrnka'. proverò le cose che hai detto. (non sono in grado di farlo ora, qui) – losingsleeep

+1

+1 Grazie, ha funzionato come un fascino. –

+0

puoi farlo in modo tale da modificare solo un campo e creare un'entità fittizia da collegare con solo la chiave primaria e il campo da modificare? – Maslow

0

non funziona quando si dispone di una proprietà su un'entità che è un ConcurrencyToken. Almeno per me. Perché allora ottieni una OptimisticConcurrencyException.

quello che faccio (e credo che questo non è una soluzione ottimale),

fatti: - io uso un nuovo contesto a causa di n-tier. Quindi, l'entità precedente/originale con i suoi valori non è nota. O si fornisce il contesto con originali e d'epoca (bah) o come me carica originale prima prima di aggiornare:

T originalItem = sessionManager.Set().Single(x => x.ID == changedEntity.ID);

 if(changedEntity.lastChangedDate != originalItem.lastChangedDate) 
      throw new OptimisticConcurrencyException(String.Format("Trying to update entity with lastChangedDate {0} using lastChangedDate {1}!", originalItem.lastChangedDate, changedEntity.lastChangedDate)); 

     ObjectStateEntry state = sessionManager.ObjectStateManager.GetObjectStateEntry(originalItem); 
     state.ApplyCurrentValues(changedEntity); 
     state.ChangeState(System.Data.EntityState.Modified); 
     sessionManager.SaveChanges(); 

Se sai qualcosa di meglio, per favore fatemelo sapere.

Atam

2

Tratto da Employee Info Starter Kit, si può considerare il frammento di codice, come di seguito:

public void UpdateEmployee(Employee updatedEmployee) 
     { 
      //attaching and making ready for parsistance 
      if (updatedEmployee.EntityState == EntityState.Detached) 
       _DatabaseContext.Employees.Attach(updatedEmployee); 
      _DatabaseContext.ObjectStateManager.ChangeObjectState(updatedEmployee, System.Data.EntityState.Modified); 
      _DatabaseContext.SaveChanges(); 
     } 
Problemi correlati