无法修改主键

时间:2014-07-01 16:19:59

标签: c# entity-framework linq-to-entities

我正在开发一个现有的大型网站项目。我有两个表:ProgramsProgramCodes

ProgramCodes包含Programs的外键。由于程序代码必须是唯一的,因此列ProgramCodes.Value已设置为主键。

CREATE TABLE [dbo].[ProgramCodes](
    [Value] [nvarchar](150) NOT NULL,
    [ProgramsId] [int] NOT NULL,
    [DateAdded] [datetime] NOT NULL,
    CONSTRAINT [PK_ProgramCodes] PRIMARY KEY CLUSTERED 
    (
        [Value] ASC
    ) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

ALTER TABLE [dbo].[ProgramCodes]  WITH CHECK ADD  CONSTRAINT [FK_ProgramCodes_Programs] FOREIGN KEY([ProgramsId])
REFERENCES [dbo].[Programs] ([ProgramsId])
GO

这没关系。但是当我们将程序标记为已删除时,程序代码需要可用于其他程序。为此,我计划通过在代码中附加“[DELETED]”来修改“已删除”程序的程序代码。

const string flag = "[DELETED]";

program.IsDeleted = true;
foreach (var programCode in program.ProgramCodes)
{
    if (!programCode.Value.EndsWith(flag))
        programCode.Value = programCode.Value + flag;
}
Repository.UnitOfWork.SaveChanges();

但是这段代码会产生以下错误:

  

属性“Value”是对象的关键信息的一部分,无法修改。

显然,此错误与我尝试修改主键的事实有关。但是没有办法在没有进入并重组整个数据库的情况下做我需要的东西吗?

1 个答案:

答案 0 :(得分:2)

在不重组数据库的情况下,最简单的方法是:

  • 复制应标记为已删除的行;
  • 删除旧的;
  • 使用新PK添加(恢复)。

但是,只有PK列从未被引用为外键才有可能。否则,需要大量工作才能正确复制或重新引用所有数据。

在这种情况下,增加一些标志字段(重组数据库)是一种更可行和可靠的行动方案。

修改

关于:

  

将数据复制到内存中,将其从数据库中删除

我不确定在EF方面进行此类操作是个好主意。为什么?因为它可能需要一些额外的事务逻辑,并且会暴露数据库的特性。

我建议将它作为一个存储过程,接受原始PK值作为参数。

它只是将有问题的行插入临时表,删除原始行,更改临时表中的PK,然后重新插入修改后的数据。我的SQL有点生疏,但这样的SP会非常简单(INSERT INTO新的临时表不需要任何DDL,因此查询将简洁明了)。