2010-08-29 100 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(); 
     }