C#WebAPI使用多个表交叉更新内部联接数据



如前一个问题所述

我愿意将这些数据更新为:

employeeTable: FirstName, LastName departmentTable: departmentName workingshift: duration

然而,现在我试图修改我的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();
}

要求:

  • 我的服务实体DSE
  • 我正在使用实体框架
  • 我的department_id是联接对象,我的shift_id也是如此
  • 我的"department_id"不是自动递增id

数据库属性:

Employee Table has employee_id, FirstName, LastName, Gender, Salary

Department Table has department_id, department_name

WorkingShift Table has shift_id, duration

问题:

假设我想更新数据如下:

EmployeeFirstName=Stack,LastName=溢出,

部门部门id=4,部门名称=Web,

ShiftShift_id=2,

在上述会话中,我应该执行什么编码?

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

我的部门表包含部门名称,所以如果我想更新我的部门名称,那么我将使用select d。我正确吗?

如果要实际更改该部门的名称,则可以选择部门实体并更改其名称。然而,这取决于你是否真的想这么做。如果一名员工指向的是一个部门ID=1,name="部门a",你想把该部门的名称改为"部门B",还是一个部门B已经用不同的ID存在?(即2(如果您将员工的部门ID指向"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();
}

Joins基本上是不必要的,因为你没有与部门或轮班做任何事情。这可以简化为:

var employee = DSE.employees.Where(e => e.department_id == 1)
.FirstOrDefault();
if (employee != null)
{
employee.department_id = 2;
DSE.SaveChanges();
}

当使用像FirstOrDefault这样的方法时,应该始终包含OrderBy类型子句,以确保获得可预测的顺序,从而获得可重复的结果。

如果你真的想更新相关数据,比如部门名称:

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

在这里,因为我们只期望一个,并且只有一个部门的ID为1,所以我们应该使用Single而不是FirstOrDefault。如果找不到部门,或者找到了一个以上的部门,则会引发异常。这个异常告诉我们找到了零行或更多行,比返回"OrDefault"方法并在路上绊倒NullReferenceException要好。

我的示例使用EF提供的Fluent方法,而不是linqQL语法,但同样的行为也可以通过这种方式实现。我只是发现流畅的方法更容易构建和链接在一起。

使用EF,真正的力量来自于通过导航属性映射关系,因此您不需要像在SQL中那样公开FK属性或手动映射Join表达式。EF可以在幕后处理所有这些。您可以加载实体,也可以急切或懒惰地加载它们的相关实体,例如查找更新数据,或者简单地从实体及其相关详细信息中选择字段,并让EF构建合适的SQL。

最新更新