PostgreSQL的实体框架核心代码优先默认值

时间:2018-11-14 10:29:52

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

到目前为止,我已经阅读了Google提出的文档,教程和其他SO问题,但似乎我错过了一些东西,但我没有(可以使用)。

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

我还决定使用ModelBuilder的流畅api来使类保持属性清洁,并在DbContext.OnModelCreating方法中定义大多数结构。 Andy也许有一次找到一种解决方案,该方法如何保持DbContext不受Postgres特定元素的影响,并将其移至迁移中...

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

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

  • int ID(自动递增ID)
  • 布尔? IsEnabled(应将默认值设置为true)
  • DateTime? 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。

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

2 个答案:

答案 0 :(得分:2)

the EF Core docs mention一样,HasDefaultValue()HasDefaultValueSql()仅指定插入新行时设置的值。将列设置为null是完全不同的事情(毕竟,null是这些列的有效值)。您可能正在寻找[计算列(https://docs.microsoft.com/en-us/ef/core/modeling/relational/computed-columns),这是另一项功能。

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

答案 1 :(得分:0)

PostgreSQL中CreateDate的解决方案:

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

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