Entity Framework Core - DefaultValue(true) attribute not working
Asked Answered
H

3

16

What is the code-first approach to set the default value of a database column in entity framework core?

Attempt #1: Using the DefaultValue attribute on the model doesn't seem to work

[DefaultValue(true)]
public bool ShowInReports { get; set; }

After running the migration, the following code is generated by dotnet ef version 5.0.1:

    migrationBuilder.AddColumn<bool>(
        name: "ShowInReports",
        table: "ParametersUsed",
        nullable: false,
        defaultValue: false);

Attempt #2: trying to define the value in OnModelCreating doesn't recognize the function:

    modelBuilder.Entity<TableName>()
        .Property(t=> t.ShowInReports)
        .HasDefaultValue(true);

Error: 'PropertyBuilder<bool>' does not contain a definition for 'HasDefaultValue' and no accessible extension method 'HasDefaultValue' accepting a first argument of type 'PropertyBuilder<bool>' could be found (are you missing a using directive or an assembly reference?)

Harwill answered 14/12, 2020 at 22:33 Comment(3)
Have you added the Microsoft.EntityFrameworkCore.Relational package?Socalled
Just figured out that for the Attempt #2, the Relational package is needed. Thanks @SocalledHarwill
Any idea how to get the DefaultValue attribute working, without using the HasDefaultValue in the OnModelCreatingHarwill
S
14

Reposting my comment, since it seems to be the answer, too.

You need to add the Microsoft.EntityFrameworkCore.Relational package for the HasDefaultValue extension method to be available.

As for the DefaultValue attribute, I'm not convinced it can be used with EF Core, or with EF in general. I might be wrong, though.

Socalled answered 14/12, 2020 at 22:49 Comment(0)
F
0

This is how you can use Data Annotations to specify a default value in EF Core

Declare a new attribute like this:

using System.Runtime.CompilerServices;

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class DefaultValueAttribute : Attribute
{
    public object? DefaultValue { get; set; }
    public object? ValueToBeConsideredDefault { get; set; }

    public DefaultValueAttribute(object? defaultValue, object? valueToBeConsideredDefault)
    {
        DefaultValue = defaultValue;
        ValueToBeConsideredDefault = valueToBeConsideredDefault;
    }

    public DefaultValueAttribute(object? defaultValue)
    {
        DefaultValue = defaultValue;
        if (defaultValue == null)
            ValueToBeConsideredDefault = null;
        else
            ValueToBeConsideredDefault = GetDefaultValue(defaultValue.GetType());
    }


    /// <summary>
    /// Taken from: https://www.meziantou.net/get-the-default-value-of-a-type-at-runtime.htm
    /// </summary>
    private static object? GetDefaultValue(Type type)
    {
        if (type.IsValueType)
            return RuntimeHelpers.GetUninitializedObject(type);

        return null;
    }
}

Put the following code in your OnModelCreating method:

var entities = builder.Model.GetEntityTypes();

foreach (var entity in entities)
    foreach (var property in entity.GetProperties())
    {
        var defaultValueAttribute = property?.PropertyInfo?.GetCustomAttribute<DefaultValueAttribute>();
        if (defaultValueAttribute == null)
            continue;

        property.SetDefaultValue(defaultValueAttribute!.DefaultValue);
        property.Sentinel = defaultValueAttribute.ValueToBeConsideredDefault;
    }

Decorate your properties with this new [DefaultValue] attribute, optionally using the 2-parameters constructor to specify "Sentinel" value (the value that EF core should consider 'default' when creating a new entity, thus replacing it with your default value. If not specified, it implicitly uses the CLR default for the default property value you specified in the attribute constructor).

Font answered 31/7, 2024 at 8:47 Comment(0)
Z
-3

public bool ShowInReports { get; set; } = true; Try this.

Zerelda answered 15/12, 2020 at 8:53 Comment(1)
Tested, doesnt work...Whap

© 2022 - 2025 — McMap. All rights reserved.