2010-08-29 2 views
10

mon code est quelque chose comme ceci:comment mettre à jour une entité dans Entity Framework .NET 4

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? 
} 
} 

maintenant s'il vous plaît me dire ce que dois-je écrire dans la méthode de mise à jour()? tout ce que j'écris, rencontre diverses exceptions. (veuillez faire attention que les données chargées sont suivies, connectées ou quelque chose comme ça)

Répondre

19

Le problème est que vos entités Person sont toujours attachées au contexte créé dans GetPersons. Si vous voulez travailler avec des entités attachées, vous devez utiliser la même instance de contexte dans les opérations select et update. Vous avez deux choix pour résoudre votre problème.

1) traitées correctement entités attachées

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) Ne pas utiliser des entités attachées

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

Merci beaucoup 'Ladislav Mrnka. Je vais essayer les choses que vous avez dites. (je suis incapable de faire cela maintenant, ici) – losingsleeep

+1

+1 Merci, a travaillé comme un charme. –

+0

pouvez-vous faire cela de telle sorte que vous modifiez seulement un champ, et créez une entité fictive à attacher avec seulement la clé primaire et le champ unique pour modifier l'ensemble? – Maslow

0

ne fonctionne pas lorsque vous avez une propriété sur l'entité qui est un ConcurrencyToken. Au moins pour moi. Parce que vous obtenez alors une OptimisticConcurrencyException.

ce que je fais (et je pense que ce n'est pas une solution optimale),

faits: - j'utiliser un nouveau contexte en raison de n-tier. Ainsi, l'entité précédente/originale avec ses valeurs n'est pas connue. Soit vous fournit le contexte avec l'original et ancien (BAH) ou comme moi charger d'origine avant la première mise à jour:

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(); 

Si vous savez quelque chose de mieux, s'il vous plaît laissez-moi savoir.

Atam

2

Tiré de Employee Info Starter Kit, vous pouvez considérer l'extrait de code comme ci-dessous:

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(); 
     } 
Questions connexes