Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HasDefaultValue not working properly for bool values #21664

Closed
ertanhasani opened this issue Jul 17, 2020 · 5 comments
Closed

HasDefaultValue not working properly for bool values #21664

ertanhasani opened this issue Jul 17, 2020 · 5 comments

Comments

@ertanhasani
Copy link

Hi,

I am trying to seed some data on my Users table (not identity Users table), but the thing is that even that I provide false value for it, HasDefaultValue(true), it adds always as true on the database. When I remove HasDefaultValue() it works perfectly, so the right value is being saved on the database. Otherwise its always true.

Steps to reproduce

Here's my UserAccount.cs (i use this for seeding data):

public class UserAccount
{
    public Guid Id { get; private set; }
    public string Email { get; set; }
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public UserRole Role { get; private set; }
    public string Password { get; set; }
    public bool IsDeleted { get; private set; }
    public bool IsActive { get; set; } = true;
}

Here's my User.cs entity:

public class User
{
    [Required]
    public string Email { get; set; }

    [Required]
    public string UserName { get; set; }

    [Required]
    public string FirstName { get; set; }

    [Required]
    public string LastName { get; set; }

    [Required]
    public UserRole Role { get; set; }

    [Required]
    public bool IsActive { get; set; } = true;
}

Here are the users that I am trying to seed:

public static UserAccount Administrator => new UserAccount()
{
    Id = Guid.Parse("8d32146e-ec0e-4fc0-8084-09b079b8586c"),
    Email = "administrator@email.com",
    FirstName = "Admin",
    LastName = "Admin",
    Role = UserRole.Admin,
    Password = "some-password"
};

public static UserAccount InactiveAdminUser => new UserAccount()
{
    Id = Guid.Parse("fc7f647b-de6a-46b3-a599-f44cd928e5be"),
    Email = "inactiveAdminUser@email.com",
    FirstName = "InactiveAdminUser",
    LastName = "InactiveAdminUser",
    Role = UserRole.Admin,
    Password = "some-password",
    IsActive = false
};

Here's my DbContext:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    SetKeys(modelBuilder);
    SeedData(modelBuilder);

    base.OnModelCreating(modelBuilder);
}

private void SeedData(ModelBuilder modelBuilder)
{
    SeedTable(modelBuilder, ConvertUserAccountToUser(Seeding.UserAccount.Administrator));
    SeedTable(modelBuilder, ConvertUserAccountToUser(Seeding.UserAccount.InactiveAdminUser));

    base.OnModelCreating(modelBuilder);
}

private void SeedTable<T>(ModelBuilder modelBuilder, T t)
    where T : class
{
    modelBuilder.Entity<T>(o =>
    {
        o.HasData(t);
    });
}

private void SetKeys(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<User>()
        .HasKey(x => x.Id);

    modelBuilder.Entity<User>()
        .Property(x => x.Email)
        .IsRequired();

    modelBuilder.Entity<User>()
        .Property(x => x.UserName)
        .IsRequired();

    modelBuilder.Entity<User>()
        .Property(x => x.FirstName)
        .IsRequired();

    modelBuilder.Entity<User>()
        .Property(x => x.LastName)
        .IsRequired();

    modelBuilder.Entity<User>()
        .Property(x => x.Role)
        .IsRequired();

    modelBuilder.Entity<User>()
        .Property(x => x.IsActive)
        .HasDefaultValue(true);
}

When I run add-migration SeedUsers here's what it being shown in `timestamp_SeedUsers.cs

migrationBuilder.InsertData(
    table: "User",
    columns: new[] { "Id", "Email", "FirstName", "IsActive", "LastName", "Role", "UserName" },
    values: new object[] { new Guid("8d32146e-ec0e-4fc0-8084-09b079b8586c"), "administrator@email.com", "Admin", true, "Admin", 2, "administrator@email.com" });

migrationBuilder.InsertData(
    table: "User",
    columns: new[] { "Id", "Email","FirstName", "LastName", "Role", "UserName" },
    values: new object[] { new Guid("fc7f647b-de6a-46b3-a599-f44cd928e5be"), "inactiveAdminUser@email.com", "InactiveAdminUser", "InactiveAdminUser", 0, "InactiveAdminUser@email.com" });

While if I remove .HasDefaultValue(true) from User.IsActive property in DbContext, then this is what i get in timestamp_SeedUsers.cs

migrationBuilder.InsertData(
    table: "User",
    columns: new[] { "Id", "Email", "FirstName", "IsActive", "LastName", "Role", "UserName" },
    values: new object[,]
    {
        { new Guid("8d32146e-ec0e-4fc0-8084-09b079b8586c"), "administrator@email.com", "Admin", true, "Admin", 2, "administrator@email.com" },
        { new Guid("fc7f647b-de6a-46b3-a599-f44cd928e5be"), "inactiveAdminUser@email.com", "InactiveAdminUser", false, "InactiveAdminUser", 0, "InactiveAdminUser@email.com" }
    });

Further technical details

EF Core version: 3.1.5
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET Core 3.1
Operating system: Windows 10 Enterprise
IDE: Visual Studio 2019 16.4.3

@ajcvickers
Copy link
Member

Duplicate of #7089. See also links in #15323 and also #15182 for a better way to handle this in EF Core 5.0

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
@Bluejanis
Copy link

@ajcvickers I have the same issue. .Net 8 (?) introduced this bug into our project, while it was still working with .Net 6 :/
Not something I would have expected from an LTS release.

@Bluejanis
Copy link

I don't see how #15182 applies to this. There, you were only talking about nullable fields. Sorry, but your link spamming did not help at all.

@Bluejanis
Copy link

I found out more:
The reason is that EF Core won't be able to know why IsActive is false.
It can either be false because you never changed the default, or because you actually intended it to be false.

Since EF Core does not know, it does not overwrite the bool value (anymore).

This breaking change was introduced with .Net 8. With older version, EF Core did actually overwrite the value.

@tomfrenzel
Copy link

I'm having the same Issue with EF Core 8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants