插入后,EF Core实体中计算的主键不会更新。

3

我有一个特殊的情况,其中表的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的值会反映出来。

但是,如果计算列是一个主键,则这个技巧不起作用。

有什么办法使这也适用于主键?


为什么不使用CasaId和ConfigurationId的复合主键呢? - juharr
你能展示一下BusinessArea实体配置(Fluent API)的代码吗? - H. Herzl
1个回答

3

这可以实现,但只能在插入时使用,需要将属性BeforeSaveBehavior设置为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,其中说:

无法将属性“Id”配置为“ValueGeneratedOnUpdate”或“ValueGeneratedOnAddOrUpdate”,因为实体添加到存储后无法更改键值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接