由 Postgres 支持的 EF Core 实体中的计算时间戳

Posted

技术标签:

【中文标题】由 Postgres 支持的 EF Core 实体中的计算时间戳【英文标题】:Computed timestamps in EF Core entity backed by Postgres 【发布时间】:2021-12-21 05:07:46 【问题描述】:

我正在为 Postgres v14 使用 EF Core v5 和 Npgsql EF Core 提供程序 v5。

我希望自动设置 CreatedAtUpdatedAt 计算列。它们都是DateTime 类型。

我试过this:

builder
  .Property(x => x.CreatedAt)
  .IsRequired()
  .HasDefaultValueSql("timestamp with time zone");

builder
  .Property(x => x.UpdatedAt)
  .IsRequired()
  .HasComputedColumnSql("timestamp with time zone", stored: true);

但是在创建表时会抛出 (Npgsql.PostgresException (0x80004005): 42601: syntax error at or near ")")。

如果我删除上面的代码,那么一切正常,因此问题与该代码无关。

我认为 timestamp with time zone 对 UTC timestamps 是正确的,但整体语法显然是错误的。我该如何解决?

【问题讨论】:

在 github 上交叉发布并在那里回答:github.com/npgsql/efcore.pg/issues/2079 【参考方案1】:

timestamp with time zone 是 Postgresql 类型名称而不是值。当前带时区的时间戳的值为current_timestampnow()。试试

.HasDefaultValueSql("now()");

【讨论】:

谢谢!请注意,它会因Npgsql.PostgresException (0x80004005): 42P17: generation expression is not immutable 而失败。我也在尝试使用here 显示的标准sql 语法,而now() 被认为是“非标准的”。但是你确认我的语法完全错误,所以谢谢你。 哦,now() 是 Postgresql 特有的。请。尝试current_timestamp 而不是now()。它在语义上相同,但 SQL 标准。 这给出了同样的例外......我认为我在某处缺少一些神奇的成分。你是对的,我使用数据类型作为值,你给我的值可能是正确的。但是 EF 提供者期待更多……但不确定是什么。再次感谢。 谁在产生错误,HasComputedColumnSql 还是 HasDefaultValueSql?您当然不能在存储的计算列中使用 volatile 表达式.. 你说得对,是HasComputedColumnSql 扔了。但是必须有办法做到这一点,因为例如我可以将HasComputedColumnSql("getutcdate()") 用于SQL Server。【参考方案2】:

使用这个:

.HasDefaultValueSql("CURRENT_TIMESTAMP");

【讨论】:

谢谢。与其他答案相同,不幸的是,在创建数据库时会导致异常。 您不能在 Postgres 的 HasComputedColumnSql 中指定可变语句。如果您希望在 UPDATE 上更新字段,则必须使用触发器。 是的,不幸的是,情况似乎如此。感谢您的确认。

以上是关于由 Postgres 支持的 EF Core 实体中的计算时间戳的主要内容,如果未能解决你的问题,请参考以下文章

EF Core性能优化

如何避免在 EF Core 中插入后选择插入的实体?

EF Core 5.0 - 更改“定义查询”映射实体时是不是需要生成迁移?

EF Core 2.0中如何手动映射数据库的视图为实体

如何直接填充由 EF Core 生成的多对多关系连接表?

EF Core 5 - 支持字段:找不到属性的指定字段