【问题标题】:Do I really have to update every property individually with Entity Framework?我真的必须使用实体框架单独更新每个属性吗?
【发布时间】: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 每次都能正常工作?

【问题讨论】:

标签: entity-framework-core


【解决方案1】:
public async Task<Employee> Update(Employee emp)
{
    _context.Entry(emp).State = EntityState.Modified;
    await _context.SaveChangesAsync();
    return employee;
}

【讨论】:

  • 欢迎来到堆栈溢出 :-) 请看How to Answer。您应该提供一些信息为什么您的代码可以解决问题。仅代码答案对社区没有用处。
  • “任何能让提问者朝着正确方向前进的答案都是有帮助的”
  • 关于您的声誉,我想您知道我的意思。 Stack Overflow 不是一个简单的“问答”论坛,而是作为提问者以外的其他人的知识库。 摘自How to Answer “简洁是可以接受的,但更全面的解释更好。” .我没有否决您的回答,也不想冒犯您。
【解决方案2】:

我不得不将我的 Repo 更改为 Scoped 而不是单例:

来自

services.AddSingleton<IEmployeeRepository, EmployeeRepository>();

到:

services.AddScoped<IEmployeeRepository, EmployeeRepository>();

【讨论】:

  • 这个解决方案有效吗?我在您上面发布的任何代码中都看不到存储库。
猜你喜欢
  • 2017-07-05
  • 1970-01-01
  • 2023-04-05
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多