我的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;
}
我甚至不需要这个: employee = emp;
我需要的是这个: _context.Update(EMP);
所以EF应该说,嘿,我需要更新一个Employee对象,我知道你通过更新传递给我的emp的ID是哪一个。 但我无法让它发挥作用。
有没有人知道如何做到这一点,或者我真的应该像第一个选项那样做?
德米特里的答案不起作用。
如果我在这里提出一个断点: 员工员工=等待 _context.Employees.SingleOrDefaultAsync(e =&gt; 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);
执行在哪里? 很难说有时是异步。
我这样做了一次。 有趣的是,当我把它放入试一试时,我就可以立即开始工作了。
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:实体类型的实例&#39;员工&#39;无法跟踪,因为此类型的另一个实例具有相同的密钥 已被跟踪。
添加新实体时, 对于大多数密钥类型,如果未设置密钥,则将创建唯一的临时密钥值(即,如果为密钥属性指定了其类型的默认值)。 如果您明确设置新实体的键值, 确保它们不会与现有实体或为其他新实体生成的临时值发生冲突。
&#34;附加现有实体时,
确保只有一个具有给定键值的实体实例附加到上下文。
在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap 1.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, Func
2 handleNode)
atLerd.Models.Concrete.EmployeeRepository.d__4.MoveNext()}&#34;
我如何摆脱这种情况,以便dbContext.Update每次都有效?
答案 0 :(得分:0)
public async Task<Employee> Update(Employee emp)
{
_context.Entry(emp).State = EntityState.Modified;
await _context.SaveChangesAsync();
return employee;
}
答案 1 :(得分:0)
我不得不将我的Repo改为Scoped而不是singleton:
这
services.AddSingleton<IEmployeeRepository, EmployeeRepository>();
为:
services.AddScoped<IEmployeeRepository, EmployeeRepository>();