属性'department_id'是对象键信息的一部分,在更新数据键时无法修改

问题描述 投票:0回答:1

根据上一个问题here

我能够将我的员工数据更新为他们的名字,姓氏,部门名称departmentName和工作班次作为持续时间。但是,现在我尝试修改我的department_id,结果显示错误消息:

属性'department_id'是对象键信息的一部分,无法修改。

这是我的查询联接数据:

var result = (from e in DSE.employees
             join d in DSE.departments on e.department_id equals d.department_id
             join ws in DSE.workingshifts on e.shift_id equals ws.shift_id

第二,这是我尝试修改department_id的代码

        var result = (from e in DSE.employees
                      join d in DSE.departments on e.department_id equals d.department_id
                      join ws in DSE.workingshifts on e.shift_id equals ws.shift_id
                      where d.department_id == 1
                      select d).FirstOrDefault();

        if (result != null)
        {
            result.department_id = 2;
            DSE.SaveChanges();
        }
  • 我的ServicesEntitiesDSE
  • 我正在使用Entities Framework
  • 我的department_id是已连接的对象,同样对我的shift_id
  • 我的`department_id'不是自动增量ID

Employee Table has employee_id, FirstName, LastName, Gender, SalaryDepartment Table has department_id, department_nameWorkingShift Table has shift_id, duration

问题:1.是否有可能通过更新三个表中的三个数据在EF中解决此问题,还是我必须在存储过程中应用解决方案?2.我需要对交叉更新表数据执行什么操作?

c# entity-framework linq stored-procedures inner-join
1个回答
0
投票

解决更改员工部门的问题:select d应该为select e以获取员工并更新员工的部门ID,而不是部门记录的ID。

我的部门表包含部门名称,因此,如果我要更新部门名称,那么我将使用select d,对吗?

如果要实际更改该部门的名称,则可以选择部门实体并更改其名称。但是,这取决于您是否真的要这样做。如果某个员工指向一个部门ID = 1,名称=“部门A”,您是否要将该部门的名称更改为“部门B”?或者部门B是否已经存在具有不同ID的信息? (即2)如果将Employee的DepartmentID指向“ 2”,则关联的部门详细信息将来自部门B,这通常就是您想要的。如果要更改部门名称(以及与部门ID 1相关的所有雇员的名称),则可以选择该部门并更新其名称。

查看您的原始代码:

var result = (from e in DSE.employees
              join d in DSE.departments on e.department_id equals d.department_id
              join ws in DSE.workingshifts on e.shift_id equals ws.shift_id
              where d.department_id == 1
              select d).FirstOrDefault();

if (result != null)
{
    result.department_id = 2;
    DSE.SaveChanges();
}

基本上不需要联接,因为您不需要对部门或班次做任何事情。可以简化为:

var employee = DSE.employees.Where(e => e.department_id == 1)
                 .FirstOrDefault();

if (employee != null)
{
    employee.department_id = 2;
    DSE.SaveChanges();
}

[使用类似FirstOrDefault的方法时,应始终包括Order By type子句,以确保获得可预测的订单以得到可重复的结果。

如果您确实要更新相关数据,例如部门名称:

var department = DSE.departments.Single(d => d.department_id == 1);
department.name = "New Name";
DSE.SaveChanges();

在这里,因为我们只期望一个部门,并且只有1个部门的ID为1,所以我们应该使用Single而不是FirstOrDefault。如果未找到任何部门,或者发现了多个部门,则将引发异常。更好的是,此异常告诉我们发现零或更多行,而不是返回“ OrDefault”方法并在随后的NullReferenceException上触发。

我的示例使用的是EF提供的Fluent方法,而不是linq QL语法,但是可以以这种方式实现相同的行为。我只是发现流利的方法更易于构建和链接在一起。

使用EF,真正的强大之处在于通过导航属性映射关系,因此您无需像在SQL中那样公开FK属性或手动映射出Join表达式。 EF可以在后台管理所有这一切。您可以加载实体,或者渴望或延迟加载它们的相关实体,例如寻找更新数据,或者简单地从实体及其相关详细信息中选择字段,然后让EF构建合适的SQL。

© www.soinside.com 2019 - 2024. All rights reserved.