【问题标题】:C# WebAPI Cross update inner join data with multiple tablesC# WebAPI 使用多个表交叉更新内部联接数据
【发布时间】:2020-06-16 11:32:21
【问题描述】:

here的上一个问题一样

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

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();
        }

要求:

  • 我的 ServicesEntitiesDSE
  • 我正在使用 实体框架
  • 我的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

问题:

假设我想按如下方式更新数据:

员工 名字 = 堆栈, 姓氏 = 溢出,

部门 部门 ID = 4, 部门名称 = 网络,

换档 Shift_id = 2,

我应该在上面的会话中执行什么编码?

【问题讨论】:

  • 您的 select d 应该是 select e 以获取员工并更新员工的部门 ID,而不是部门记录的 ID。
  • 嗨@StevePy 太好了,我犯了这样的错误真是太棒了...所以我成功地更新了employee table 中的department_id。这是一个后续问题,我的 department 表包含 department_name 所以如果我想更新我的 department_name 那么我将使用select d am我说对了吗?
  • @StevePy 我应该这样说,我想更改 employee FirstNamedepartment_name 等数据跨越两个表,我应该在上面写什么查询?
  • 嗨@Nasir 当我遵循史蒂夫给出的解决方案时,我没有遇到上述错误

标签: c# entity-framework linq stored-procedures inner-join


【解决方案1】:

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

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

如果您想实际更改该部门的名称,则可以选择部门实体并更改其名称。但是,这取决于这是否真的是您想要做的。如果员工指向的部门 ID = 1,名称 =“部门 A”,您想将该部门的名称更改为“部门 B”,还是已经存在具有不同 ID 的部门 B? (即 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();
}

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

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。如果没有找到部门,或者找到超过 1 个部门,则会抛出异常。这个异常告诉我们找到零个或多个行比返回“OrDefault”方法并在路上绊倒NullReferenceException 更好。

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

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

【讨论】:

    猜你喜欢
    • 2021-12-24
    • 1970-01-01
    • 2017-01-15
    • 1970-01-01
    • 2014-01-21
    • 1970-01-01
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多