插入后计算的主键不会在 EF Core 实体中更新
Computed primary key doesn't get updated in EF Core entity after insert
我有一个特殊情况,其中 table 的 Id 被定义为计算列,如下所示:
CREATE TABLE [BusinessArea](
[Id] AS (isnull((CONVERT([nvarchar],[CasaId],(0))+'-')+CONVERT([nvarchar],[ConfigurationId],(0)),'-')) PERSISTED NOT NULL,
[CasaId] [int] NOT NULL,
[ConfigurationId] [int] NOT NULL,
[Code] [nvarchar](4) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_BusinessArea] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
GO
通常当我有一个计算列时,我会这样配置它:
builder.Entity<MyEntity>()
.Property(p => p.MyComputed).HasComputedColumnSql(null);
对于 .HasComputedColumnSql()
,MyComputed 的值反映在实体上的 insert/update。
但是,如果计算列是 PK,则此技巧无效。
知道如何使用 PK 来实现吗?
它可以工作,但只能用于插入,通过设置 属性 BeforeSaveBehavior to Ignore:
modelBuilder.Entity<BusinessArea>().Property(e => e.Id)
.Metadata.BeforeSaveBehavior = PropertySaveBehavior.Ignore;
但通常这样的设计会导致 EF Core 出现问题,因为它不支持可变键(主键或备用键)。这意味着它永远不会在更新后从数据库中检索回 Id
。您可以通过将 属性 标记为 ValueGeneratedOnAddOrUpdate(这是计算列的正常行为)来验证:
modelBuilder.Entity<BusinessArea>().Property(e => e.Id)
.ValueGeneratedOnAddOrUpdate();
如果你这样做,EF Core 将抛出 InvalidOperationException
说
The property 'Id' cannot be configured as 'ValueGeneratedOnUpdate' or 'ValueGeneratedOnAddOrUpdate' because the key value cannot be changed after the entity has been added to the store.
我有一个特殊情况,其中 table 的 Id 被定义为计算列,如下所示:
CREATE TABLE [BusinessArea](
[Id] AS (isnull((CONVERT([nvarchar],[CasaId],(0))+'-')+CONVERT([nvarchar],[ConfigurationId],(0)),'-')) PERSISTED NOT NULL,
[CasaId] [int] NOT NULL,
[ConfigurationId] [int] NOT NULL,
[Code] [nvarchar](4) NOT NULL,
[Name] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_BusinessArea] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]
GO
通常当我有一个计算列时,我会这样配置它:
builder.Entity<MyEntity>()
.Property(p => p.MyComputed).HasComputedColumnSql(null);
对于 .HasComputedColumnSql()
,MyComputed 的值反映在实体上的 insert/update。
但是,如果计算列是 PK,则此技巧无效。
知道如何使用 PK 来实现吗?
它可以工作,但只能用于插入,通过设置 属性 BeforeSaveBehavior to Ignore:
modelBuilder.Entity<BusinessArea>().Property(e => e.Id)
.Metadata.BeforeSaveBehavior = PropertySaveBehavior.Ignore;
但通常这样的设计会导致 EF Core 出现问题,因为它不支持可变键(主键或备用键)。这意味着它永远不会在更新后从数据库中检索回 Id
。您可以通过将 属性 标记为 ValueGeneratedOnAddOrUpdate(这是计算列的正常行为)来验证:
modelBuilder.Entity<BusinessArea>().Property(e => e.Id)
.ValueGeneratedOnAddOrUpdate();
如果你这样做,EF Core 将抛出 InvalidOperationException
说
The property 'Id' cannot be configured as 'ValueGeneratedOnUpdate' or 'ValueGeneratedOnAddOrUpdate' because the key value cannot be changed after the entity has been added to the store.