Entity Framework Core code первые значения по умолчанию для PostgreSQL

До сих пор я читал документы, учебные пособия, подготовленные Google, и другие вопросы SO, но, похоже, я что-то пропустил, и у меня это не получилось (для работы).

Я пытаюсь реализовать действительно крошечную базу данных PostgreSQL для веб-API .NET Core 2.1 (микросервиса). Я привык к первому подходу к базе данных, но для этой услуги я решил сначала попробовать код.

Я также решил использовать свободный API ModelBuilder, чтобы уберечь классы от атрибутов и определить большую часть структуры в методе DbContext.OnModelCreating. Энди, возможно, однажды найдет решение, как очистить DbContext от конкретных элементов Postgres и переместить их в миграции ...

Моя проблема в том, что требования определяют множество значений по умолчанию, и я не могу заставить их работать так, как они должны себя вести.

Например, у меня есть таблица Entity1, в которой всего 3 столбца:

  • int Id (автоматически увеличивающийся идентификатор)
  • булево? IsEnabled (который должен получить значение по умолчанию true)
  • DateTime? LastStatusChange (отметка времени без часового пояса, которая должна быть установлена ​​при создании или обновлении до значения по умолчанию CURRENT_TIMESTAMP)

Идея значения по умолчанию для метки времени состоит в том, чтобы база данных была единственным экземпляром, создающим метки времени и использующим значения по умолчанию db в качестве конфигурации для всех запущенных экземпляров. Например. когда требования изменяются на «значение по умолчанию теперь должно быть ложным», мы просто изменяем значения по умолчанию 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.

В любом случае, чтобы получить значения по умолчанию db при обновлении через ядро ​​entity framework?


person monty    schedule 14.11.2018    source источник
comment
Установка значения null не должна вызывать значение по умолчанию. Как с помощью этого подхода кто-то на самом деле поместит в базу данных null? Я не ненавижу, просто указываю на это. Если бы это сработало так, как вы предполагаете, был бы другой лагерь, говорящий, если бы я установил для него значение null, почему бы не использовать null? ............ но проголосуйте за сам вопрос.   -  person granadaCoder    schedule 07.01.2020
comment
Для будущих читателей я смог заставить это работать для НОВЫХ строк: builder.Property (t = ›t.MyColumnCreateDate) .HasDefaultValueSql (CURRENT_TIMESTAMP); Не требовалось ни ValueGeneratedOnAddOrUpdate, ни HasColumnType (по умолчанию он был равен «отметке времени без часового пояса») (PostgreSQL 12.1, скомпилирован Visual C ++ build 1914, 64-разрядная версия) Я думаю, вам придется использовать триггер при UPDATE. Это похоже на ответ @GetoX, но не с использованием проприетарного NOW ()   -  person granadaCoder    schedule 07.01.2020


Ответы (2)


Как указано в документах EF Core, HasDefaultValue() и HasDefaultValueSql() указывают только значение, которое устанавливается при вставке новой строки. Установка для столбца значения null - это совершенно другое дело (в конце концов, null является допустимым значением для этих столбцов). Возможно, вам нужны вычисляемые столбцы, что это другая особенность.

К сожалению, как в документах Npgsql упоминается, вычисляемые столбцы в настоящее время не поддерживаются PostgreSQL. Это можно настроить с помощью триггеров базы данных PostgreSQL, но это не так. не управляется EF Core, поэтому вам придется использовать SQL в своих миграциях, чтобы настроить это.

person Shay Rojansky    schedule 14.11.2018
comment
Обратите внимание, что поддержка (хранимых) вычисляемых столбцов была добавлена ​​в PostgreSQL 12, и они также поддерживаются поставщиком Npgsql EF Core (см. документацию). - person Shay Rojansky; 10.04.2020

Решение для CreateDate в PostgreSQL:

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

К сожалению, для события обновления нет решения.

person GetoX    schedule 11.09.2019
comment
Для будущих читателей, если вы хотите использовать непатентованную функцию (СЕЙЧАС), вы можете сделать это: builder.Property (t = ›t.MyColumnCreateDate) .HasDefaultValueSql (CURRENT_TIMESTAMP); - person granadaCoder; 07.01.2020