我的代码是这样的:
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()方法中写什么? 我写的一切,遇到各种例外。 (请注意加载的数据是跟踪,连接或类似的)
答案 0 :(得分:20)
问题是您的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();
}
}
}
答案 1 :(得分: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();
}
答案 2 :(得分:0)
不起作用。 至少对于我来说。因为然后你得到一个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();
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