【问题标题】:Entity Framework Core code first default values for PostgreSQLPostgreSQL 的 Entity Framework Core 代码第一个默认值
【发布时间】:2019-04-17 06:59:36
【问题描述】:

到目前为止,我阅读了谷歌提出的文档、教程和其他 SO 问题,但似乎我错过了一些东西,但我不明白(工作)。

我尝试为 .NET Core 2.1 Web api(微服务)实现一个非常小的 PostgreSQL 数据库。我习惯了数据库优先的方法,但对于这项服务,我决定尝试代码优先的方法。

我还决定使用 ModelBuilder 的 fluent api 来保持类与属性无关,并在 DbContext.OnModelCreating 方法中定义大部分结构。安迪也许有一次会找到一种解决方案,如何让 DbContext 从 Postgres 特定元素中保持干净,并将它们移动到迁移中......

我的问题是需求定义了很多默认值,我无法让它们按应有的方式工作。

例如,我有表 Entity1,它只有 3 列:

  • int Id(自动递增 id)
  • 布尔? IsEnabled(应该得到默认值 true)
  • 日期时间? LastStatusChange(不带时区的时间戳,应在创建时设置或更新为默认值 CURRENT_TIMESTAMP)

时间戳默认值背后的想法是让数据库作为单个实例创建时间戳,并使用 db 默认值作为所有正在运行的实例的配置。例如。当需求更改为“默认值现在应该为 false”时,我们只需更改现有数据库中的 db 默认值并更新迁移以获取新的分期付款。

我的modelBuilder代码目前是:

  modelBuilder.Entity<Entity1>(entity =>
  {
    entity.HasKey(e => e.Id);

    entity.Property(e => e.Id)
      .ValueGeneratedOnAdd();

    entity.Property(e => e.IsEnabled)
      .HasDefaultValue(true)
      .ValueGeneratedOnAddOrUpdate();

    entity.Property(e => e.LastStatusChange)
      .HasColumnType("timestamp without time zone")
      .HasDefaultValueSql("CURRENT_TIMESTAMP")
      .ValueGeneratedOnAddOrUpdate();
  });

这适用于新创建的值。

切换或重置我使用的字段时

entity.LastStatusChange = null;

和或

entity.IsEnabled = null;

我假设将它们设置为 null 会触发创建默认值,但这不会影响 LastStatusChange 字段(值保持不变)并将 IsEnabled 设置为 null。

是否通过实体框架核心在更新时获取数据库默认值?

【问题讨论】:

  • 设置为 null 不应触发默认值。有人会如何使用这种方法将 null 放入数据库中?我不是讨厌,只是指出来。如果它像你建议的那样工作,那么会有另一个“阵营”说“如果我将它设置为 null,为什么不使用 null ?”............但赞成这个问题本身.
  • 对于未来的读者,我能够让它适用于新行:builder.Property(t => t.MyColumnCreateDate).HasDefaultValueSql("CURRENT_TIMESTAMP");不需要 ValueGeneratedOnAddOrUpdate,也不需要 HasColumnType(它默认为“没有时区的时间戳”)(“PostgreSQL 12.1,由 Visual C++ build 1914 编译,64 位”)我认为您必须在 UPDATE 上使用触发器。这类似于@GetoX 的答案,但不使用专有的 NOW()

标签: postgresql .net-core entity-framework-core npgsql .net-core-2.1


【解决方案1】:

the EF Core docs mentionHasDefaultValue()HasDefaultValueSql() 仅指定插入新行时设置的值。将列设置为 null 是完全不同的事情(毕竟 null 是这些列的有效值)。您可能正在寻找computed columns,这是一个不同的功能。

不幸的是,正如the Npgsql docs mention,PostgreSQL 目前不支持计算列。可以使用 PostgreSQL database triggers 进行设置,但这不是由 EF Core 管理的,因此您必须在迁移中使用 SQL 进行设置。

【讨论】:

  • 请注意,(存储的)计算列支持已添加到 PostgreSQL 12 中,并且 Npgsql EF Core 提供程序 (see the docs) 也支持它们。
【解决方案2】:

PostgreSQL 中 CreateDate 的解决方案:

builder.Property(e => e.CreationDate)
  .HasColumnType("timestamp without time zone")
  .HasDefaultValueSql("NOW()")
  .ValueGeneratedOnAdd();

很遗憾,更新事件没有解决方案。

【讨论】:

  • 对于未来的读者,如果你想使用非专有函数(NOW),你可以这样做:builder.Property(t => t.MyColumnCreateDate).HasDefaultValueSql("CURRENT_TIMESTAMP");跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-23
  • 2017-10-08
  • 1970-01-01
  • 2013-11-02
  • 2016-09-27
相关资源
最近更新 更多