如何生成sql命令来使用其他列更新主键



Postgres数据库包含产品表,自然主键:

create table product 
(
productcode char(10) primary key,
price numeric(12,2),
... a lot of other columns
);

和其他具有自然主键的类似表

ASP。使用。NET 5 MVC应用程序,使用EF Core进行更新Npgsql数据提供程序。

如果产品代码也改变了,EF Core抛出错误

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

产品代码在其他表中用作外键(带有ON UPDATE CASCADE子句),因此无法删除。

数据库结构更改不是一个选项。

如何允许主键列的更新?

的一些想法:

  1. 在EF Core中阻止此检查,例如在更新之前强制设置旧值与新值相同

  2. 在保存更改前将主键设置为其他值

  3. 强制EF Core创建update语句并手动执行

  4. 使用一些EF Core扩展或其他框架

  5. 修改Npgsql EF core provider以允许此操作

在不改变数据库结构的情况下实现这个最好的方法是什么?

异常抛出在

行https://github.com/dotnet/efcore/blob/f62cf1b1fa45d6026e8f98113d6d6712d81094c3/src/EFCore/ChangeTracking/Internal/ChangeDetector.cs L107

private static void ThrowIfKeyChanged(InternalEntityEntry entry, IProperty property)
{
if (property.IsKey()
&& property.GetAfterSaveBehavior() == PropertySaveBehavior.Throw)
{
throw new InvalidOperationException(CoreStrings.KeyReadOnly(property.Name, entry.EntityType.DisplayName()));
}
}

是否可以将此注释掉并编译新的EF Core dll

由于您正在更改主键,因此实际上它不是更新,而是添加新产品。所以

  1. 从现有产品创建新产品,该产品将具有新的产品代码

  2. 更新所有表中具有先前产品代码的所有项,用新的外键替换先前的外键。

  3. 在此之后,您可以删除之前的产品。

如果您尝试关闭验证并更改代码,在此之后您的数据库将被破坏,并且您将无法再次使用它,因为您将不断地遇到集成错误。