将主键修改为外键时出错

Posted

技术标签:

【中文标题】将主键修改为外键时出错【英文标题】:Error when modifying a primary key as a foreign key 【发布时间】:2021-11-23 22:20:30 【问题描述】:

我在实体框架中有一个主键作为外键。

public class RailcarTrip

    [Key, ForeignKey("WaybillRailcar")]
    public int WaybillRailcarId  get; set; 
    public WaybillRailcar WaybillRailcar  get; set; 

    // Etc.

这似乎工作正常,并生成下表。

CREATE TABLE [dbo].[RailcarTrips](
    [WaybillRailcarId] [int] NOT NULL,
    [StartDate] [datetime2](7) NOT NULL,
    [DeliveryDate] [datetime2](7) NULL,
    [ReleaseDate] [datetime2](7) NULL,
    [ReturnDate] [datetime2](7) NULL,
    [DeliveryEta] [datetime2](7) NULL,
    [ReleaseEta] [datetime2](7) NULL,
    [ReturnEta] [datetime2](7) NULL,
    [ReturnCity] [nvarchar](80) NULL,
    [ReturnState] [nvarchar](2) NULL,
    [TripType] [int] NOT NULL,
 CONSTRAINT [PK_RailcarTrips] PRIMARY KEY CLUSTERED 
(
    [WaybillRailcarId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[RailcarTrips]  WITH CHECK ADD  CONSTRAINT [FK_RailcarTrips_WaybillRailcars_WaybillRailcarId] FOREIGN KEY([WaybillRailcarId])
REFERENCES [dbo].[WaybillRailcars] ([Id])
ON DELETE CASCADE
GO

ALTER TABLE [dbo].[RailcarTrips] CHECK CONSTRAINT [FK_RailcarTrips_WaybillRailcars_WaybillRailcarId]
GO

但是当我尝试更改此 PK/FK 以使其引用不同的记录时出现错误。

“RailcarTrip.WaybillRailcarId”属性是键的一部分,因此不能修改或标记为已修改。要使用标识外键更改现有实体的主体,首先删除依赖项并调用“SaveChanges”,然后将依赖项与新主体关联。

我不明白为什么这是个问题?主键未设置为实体/自动设置。此代码应该是 FK 的简单更新。我不想删除任何东西。谁能解释为什么这是个问题?

这似乎是实体框架错误,而不是 SQL Server 错误。

【问题讨论】:

为什么您不添加自动增量主键而忘记这一点。否则在整个项目开发过程中你会一个接一个的出现问题。 @Serge:因为,作为 PK/FK,我需要能够将此 PK 设置为特定的行 ID。 Entity Framework 将自动使 PK 自动递增。但它在这里没有正确地做到这一点。 这将使更改 FK 的成本更低,并使 EF 能够支持该操作。 【参考方案1】:

EF 不支持修改主键。因此,您需要删除并插入(Remove+SaveChanges+Add+SaveChanges)RailCarTrip 以将其移动到不同的 WaybillRailcar。或者,您可以直接在 TSQL 中更新 PK/FK。

【讨论】:

也可以通过存储过程来完成 谢谢,似乎发送原始 SQL 命令是最高效的答案。我不明白为什么 EF 会阻止这一点。我可能需要一次对任意数量的记录执行此操作。 经过仔细考虑,我明白为什么这可能不是最好的方法。也许我会修改它,以便我有一个单独的 PK 和 FK,并在 FK 上放置一个唯一的索引。【参考方案2】:

如果我对您的理解正确,那就是您想要更改实体主键的值 (RailcarTrip),而不是您已经回答了您自己的问题 - EF 通知您,主键不是可修改的值,这对于 SQL 数据库是正确的。 此键是否也是外键无关紧要。 要修改主键值,必须删除相应的条目并使用新的键值重新创建它。

【讨论】:

SQL Server(和 Azure SQL 数据库)支持更新主键,这很少是个好主意。 正如@DavidBrowne-Microsoft 所指出的,这是允许的。我不知道为什么这不是一个好主意。这似乎是一个好主意。不管怎样,我不明白为什么 EF 不允许这样做。 实体是由 PK 跟踪的,所以它会使更改跟踪复杂化。理论上这不是一个棘手的问题,但 EF 只是没有实现它。

以上是关于将主键修改为外键时出错的主要内容,如果未能解决你的问题,请参考以下文章

数据表操作与主键外键唯一键使用

如何在laravel中将主键本身设置为外键?

dbeaver如何进行级联删除和修改

mysql添加外键失败

MySQL INSERT INTO inside UPDATE 并将新主键设置为外键

如何将主键和外键添加到 BigQuery?