实体类型的实例' XY'无法跟踪,因为已经跟踪了{' XId',' YId'}的另一个具有相同键值的实例

时间:2018-04-06 09:11:07

标签: c# asp.net-core-mvc entity-framework-core

很抱歉再次举起这个 - 我在这里看到了很多次但我仍然对我的情况感到困惑,特别是因为我似乎能够克服'它,但我不确定我喜欢怎么做,我很想知道为什么。

我在Staff和Departments之间有很多关系,StaffDepartment表设置了一个复合键,如下所示:

modelBuilder.Entity<StaffDepartment>() .HasKey(sd => new { sd.StaffId, sd.DepartmentId });

我怀疑这必须与我有时会得到的例外有关:

InvalidOperationException: The instance of entity type 'StaffDepartment' cannot be tracked because another instance with the same key value for {'StaffId', 'DepartmentId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

我有时会说,因为,奇怪的是,如果我更改了员工详细信息页面中的部门并进行了更新,那么它会很顺利,但是当我保留它时(例如,可能只是更改员工姓名)我会收到此异常。

我尝试对此实施各种建议 similar but apparently different SO discussion 以及各种修改我的存储库更新方法的方法,奇怪的是,这是我使用它的唯一方法:

public async Task UpdateStaff(StaffDto staff)
        {
            var staffToUpdate = await _db.Staff
                .Include(d => d.Departments)
                .ThenInclude(d => d.Department)
                .SingleOrDefaultAsync(s => s.Id == staff.Id);

            // Without either these two line I get the exception
              _db.StaffDepartment.RemoveRange(staffToUpdate.Departments);
              await _db.SaveChangesAsync();               

            _mapper.Map(staff, staffToUpdate);
            await _db.SaveChangesAsync();
        }

所以我应该用同样的方法两次调用SaveChangesAsync()似乎很奇怪。那里到底发生了什么?如果不这样做,我将如何在错误When attaching existing entities, ensure that only one entity instance with a given key value is attached中实现建议。

实体类看起来像这样:

public class Staff
    {
        public int Id { get; set; }
        ...
        public ICollection<StaffDepartment> Departments { get; set; }
    }

public class Department
    {
        public int DepartmentId { get; set; }
        ...
        public ICollection<StaffDepartment> Staff { get; set; }
    }

public class StaffDepartment
    {
        public int StaffId { get; set; }
        public Staff Staff { get; set; }
        public int DepartmentId { get; set; }
        public Department Department { get; set; }

    }

从域名等回来的staffDto就是:

public class StaffDto
    {
        public int Id { get; set; }
        ...
        public List<DepartmentDto> Departments { get; set; }
    }

存储库全部注册为瞬态,即

services.AddTransient<ICPDRepository, CPDRepository>();

0 个答案:

没有答案