【发布时间】:2017-02-08 20:44:19
【问题描述】:
我的 Web API 存储库中有一个如下所示的更新方法(在 EF Core 中):
public async Task<Employee> Update(Employee emp)
{
Employee employee = await
_context.Employees.SingleOrDefaultAsync(e => e.ID == emp.ID);
if (employee == null)
{
return null;
}
employee.FirstName = emp.FirstName;
employee.LastName = emp.LastName;
employee.Supervisor = emp.Supervisor;
employee.OfficeBureau = emp.OfficeBureau;
employee.Notes = emp.Notes;
await _context.SaveChangesAsync();
return employee;
}
它工作得很好。但我们真的必须这样做吗? 我想做更多类似的事情并一次性更新所有实体属性:
public async Task<Employee> Update(Employee emp)
{
Employee employee = await
_context.Employees.SingleOrDefaultAsync(e => e.ID == emp.ID);
if (employee == null)
{
return null;
}
employee = emp;
_context.Update(employee);
await _context.SaveChangesAsync();
return employee;
}
我什至不需要这个: 员工 = emp;
我只需要这个: _context.Update(emp);
所以 EF 应该说,嘿,我需要更新一个 Employee 对象,并且我通过更新时传递给我的 emp 的 ID 知道它是哪一个。 但我就是无法让它工作。
有人知道怎么做吗?或者我真的应该像第一个选项那样做吗?
Dmitry 的以下回答无效。
如果我在这里设置一个断点: 雇员雇员=等待 _context.Employees.SingleOrDefaultAsync(e => e.ID == emp.ID);
然后尝试一步一步,执行似乎被这一行吞没了:
_context.Entry(emp).State = EntityState.Modified;
然后这是返回的响应: {}
并且数据库中的员工没有改变。
也试过这个:
public async Task<Employee> Update(Employee emp)
{
Employee employee = await
_context.Employees.SingleOrDefaultAsync(e => e.ID == emp.ID);
if (employee == null)
{
return null;
}
EntityEntry<Employee> entity = _context.Employees.Attach(emp);
entity.State = EntityState.Modified;
_context.Employees.Update(emp);
await _context.SaveChangesAsync();
return employee;
}
但同样的事情。 执行在这里被吞没了:
EntityEntry<Employee> entity = _context.Employees.Attach(emp);
执行在哪里? 有时很难用异步来判断。
我让它像这样工作一次。 有趣的是,当我将它放入 try/catch 时,我必须立即开始工作。
public async Task<Employee> Update(Employee emp)
{
Employee employee = await
_context.Employees.SingleOrDefaultAsync(e => e.ID == emp.ID);
if (employee == null)
{
return null;
}
try
{
_context.Employees.Update(emp);
}
catch(Exception ex)
{
throw ex;
}
await _context.SaveChangesAsync();
return emp;
}
但它只工作了一次。 现在它一直抛出这个异常。
{System.InvalidOperationException:无法跟踪实体类型“Employee”的实例,因为该类型的另一个实例具有相同的键 已被跟踪。
添加新实体时, 对于大多数键类型,如果没有设置键(即,如果键属性被分配为其类型的默认值),将创建一个唯一的临时键值。 如果您要为新实体显式设置键值, 确保它们不会与现有实体或为其他新实体生成的临时值发生冲突。
"当附加现有实体时,
确保只有一个具有给定键值的实体实例附加到上下文。
在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap1.Add(TKey key, InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityGraphAttacher.PaintAction(EntityEntryGraphNode node)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.EntityEntryGraphIterator.TraverseGraph(EntityEntryGraphNode node, Func2 handleNode)
在 Microsoft.EntityFrameworkCore.DbContext.SetEntityState[TEntity](TEntity entity, EntityState entityState) 在 Lerd.Models.Concrete.EmployeeRepository.d__4.MoveNext()}"
如何摆脱这种情况,以便 dbContext.Update 每次都能正常工作?
【问题讨论】: