2010-08-29 98 views
10

我的代碼是這樣的:如何更新實體在實體框架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? 
} 
} 

現在請告訴我,我應該在Update()方法寫? 我寫的一切,遇到了各種例外。 (請注意,加載的數據是跟蹤,連接或類似的東西)

回答

19

問題是,你的Person實體仍附加到在GetPersons中創建的上下文。如果要使用附加實體,則必須在選擇和更新操作中使用相同的上下文實例。你有兩個選擇來解決你的問題。

1)正確處理連接實體

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)不要使用連接實體

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

非常感謝你 '拉吉斯拉夫Mrnka'。 我會嘗試你說的話。 (我現在無法做到這一點,在這裏) – losingsleeep 2010-08-29 12:47:46

+1

+1謝謝,像一個魅力工作。 – 2010-09-10 23:20:12

+0

你能以這樣一種方式做到這一點嗎,你只需要改變一個字段,並創建一個虛擬實體來附加只有主鍵和一個字段來修改set? – Maslow 2011-10-19 17:06:25

0

不工作的時候,你有實體屬性,它是一個ConcurrencyToken。 至少對我而言。因爲你然後得到一個OptimisticConcurrencyException。

我做什麼(我認爲這不是一個最佳的解決方案),

事實: - 我用一個新的上下文,因爲n層的。所以,以前的/原始的實體及其值是未知的。要麼你用原來的老(BAH)提供的上下文或像我原來加載首先更新前:

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

如果你知道更好的東西,請讓我知道。

ATAM

2

Employee Info Starter Kit服用,可以考慮代碼片段如下:

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