我是否真的必须使用实体框架单独更新每个属性?

时间:2017-02-08 20:44:19

标签: entity-framework-core

我的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每次都有效?

2 个答案:

答案 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>();