Созданные значения

Столбцы базы данных могут создавать свои значения различными способами: столбцы первичного ключа часто являются автоматически добавочными целыми числами, другие столбцы имеют значения по умолчанию или вычисляемые значения и т. д. На этой странице описаны различные шаблоны создания значений конфигурации с помощью EF Core.

Значения по умолчанию

В реляционных базах данных столбец можно настроить со значением по умолчанию; Если строка вставляется без значения для этого столбца, будет использоваться значение по умолчанию.

Можно настроить значение по умолчанию для свойства:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Rating)
        .HasDefaultValue(3);
}

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

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}

Вычисляемые столбцы

В большинстве реляционных баз данных столбец можно настроить для вычисления значения в базе данных, как правило, с выражением, ссылающимся на другие столбцы:

modelBuilder.Entity<Person>()
    .Property(p => p.DisplayName)
    .HasComputedColumnSql("[LastName] + ', ' + [FirstName]");

В приведенном выше примере создается виртуальный вычисляемый столбец, значение которого вычисляется каждый раз, когда оно извлекается из базы данных. Кроме того, можно указать, что вычисляемый столбец хранится (иногда называется сохраненным), то есть вычисляется при каждом обновлении строки и хранится на диске вместе с обычными столбцами:

modelBuilder.Entity<Person>()
    .Property(p => p.NameLength)
    .HasComputedColumnSql("LEN([LastName]) + LEN([FirstName])", stored: true);

Первичные ключи

По соглашению не составные первичные ключи типа short, int, long или Guid настраиваются для вставленных сущностей, если значение не предоставляется приложением. Поставщик базы данных обычно заботится о необходимой конфигурации; Например, числовой первичный ключ в SQL Server автоматически настраивается как столбец IDENTITY.

Дополнительные сведения см. в документации по ключам и рекомендациям по конкретным стратегиям сопоставления наследования.

Явное настройка создания значений

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

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public DateTime Inserted { get; set; }
}

Аналогичным образом можно настроить свойство, чтобы его значение было создано при добавлении или обновлении:

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public DateTime LastUpdated { get; set; }
}

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

Например, в SQL Server, когда свойство GUID настроено как первичный ключ, поставщик автоматически выполняет создание значений на стороне клиента с помощью алгоритма для создания оптимальных последовательных значений GUID. Однако указание ValueGeneratedOnAdd свойства DateTime не будет иметь никакого эффекта (см. раздел ниже для создания значений DateTime).

Аналогичным образом свойства byte[], настроенные как созданные при добавлении или обновлении и помеченные как маркеры параллелизма, настраиваются с типом данных rowversion, чтобы значения автоматически создавались в базе данных. Однако указание ValueGeneratedOnAdd не действует.

Ознакомьтесь с документацией поставщика по определенным методам создания значений, которые он поддерживает. Здесь приведена документация по поколению значений SQL Server.

Создание значений даты и времени

Общий запрос — иметь столбец базы данных, содержащий дату и время первой вставки строки (значение, созданное при добавлении), или время последнего обновления (значение, созданное при добавлении или обновлении). Так как для этого существуют различные стратегии, поставщики EF Core обычно не настраивают автоматическое создание значений для столбцов даты и времени. Это необходимо настроить самостоятельно.

Метка времени создания

Настройка столбца даты и времени для создания метки времени создания строки обычно является вопросом настройки значения по умолчанию с соответствующей функцией SQL. Например, в SQL Server можно использовать следующее:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .Property(b => b.Created)
        .HasDefaultValueSql("getdate()");
}

Не забудьте выбрать соответствующую функцию, так как может существовать несколько (например GETDATE() , vs. GETUTCDATE()).

Обновление метки времени

Хотя сохраненные вычисляемые столбцы кажутся хорошим решением для управления метками времени последнего обновления, базы данных обычно не позволяют указывать такие функции, как GETDATE() в вычисляемом столбце. В качестве альтернативы можно настроить триггер базы данных для достижения того же эффекта:

CREATE TRIGGER [dbo].[Blogs_UPDATE] ON [dbo].[Blogs]
    AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    IF ((SELECT TRIGGER_NESTLEVEL()) > 1) RETURN;

    UPDATE B
    SET LastUpdated = GETDATE()
    FROM dbo.Blogs AS B
    INNER JOIN INSERTED AS I
        ON B.BlogId = I.BlogId
END

Сведения о создании триггеров см. в документации по использованию необработанных SQL в миграциях.

Переопределение создания значений

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

Чтобы переопределить создание значений с явным значением, просто задайте для свойства любое значение, которое не является значением по умолчанию среды CLR для типа этого свойства (nullдля string0 , Guid.Empty для , для intGuidи т. д.).

Примечание.

Попытка вставки явных значений в SQL Server IDENTITY завершается ошибкой по умолчанию; См. эти документы для обходного решения.

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

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>().Property(b => b.LastUpdated)
        .ValueGeneratedOnAddOrUpdate()
        .Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Save);
}

Нет создания значений

Помимо определенных сценариев, таких как описанные выше, свойства обычно не имеют настроенного поколения значений; это означает, что приложение должно всегда предоставлять значение, которое нужно сохранить в базе данных. Это значение должно быть назначено новым сущностям, прежде чем они будут добавлены в контекст.

Однако в некоторых случаях может потребоваться отключить создание значений, которое было настроено по соглашению. Например, первичный ключ типа int обычно неявно настраивается как надстройка с созданием значений (например, столбец удостоверений в SQL Server). Это можно отключить с помощью следующих действий:

public class Blog
{
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int BlogId { get; set; }

    public string Url { get; set; }
}