代码之家  ›  专栏  ›  技术社区  ›  gsharp

插入后,计算出的主键不会在EF核心实体中更新

  •  2
  • gsharp  · 技术社区  · 6 年前

    我有一个特殊情况,表的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的值反映了对实体的插入/更新。

    但是,如果计算列是一个pk,这个技巧就不起作用。

    你知道如何使它也能与pk一起工作吗?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Ivan Stoev    6 年前

    可以通过设置属性使其工作,但只能用于插入 BeforeSaveBehavior Ignore :

    modelBuilder.Entity<BusinessArea>().Property(e => e.Id)
        .Metadata.BeforeSaveBehavior = PropertySaveBehavior.Ignore;
    

    但一般来说,这种设计会导致ef内核出现问题,因为它不支持可变密钥(主密钥或备用密钥)。这意味着它将永远无法收回 Id 更新后来自数据库。您可以通过将属性标记为 ValueGeneratedOnAddOrUpdate (这是计算列的正常行为):

    modelBuilder.Entity<BusinessArea>().Property(e => e.Id)
        .ValueGeneratedOnAddOrUpdate();
    

    如果你这样做,英孚核心会投 InvalidOperationException

    无法将属性“id”配置为“valueGeneratedOnUpdate”或“valueGeneratedOnadOrUpdate”,因为在将实体添加到存储区后无法更改键值。

    推荐文章