Default Value + HasData generates incorrect migration
- Dominant language
- C#
- Stars
- 14.8k
- Forks
- 3.4k
- PR merge metrics
- PR metrics pending
Description
### Bug description
Hey folks,
I'm in the middle of a project right now, and I'm using `HasData` to seed values for static, lookup type tables. I just discovered that there's a bizarre behavior in the migration generation when default values are specified on a non-nullable boolean column.
Inside of `HasData`, I'm supplying a new entity with the boolean set to `false`. The result is that the migration excludes that value from the migration, resulting in a `true` value being inserted into the database. My expectation is that it would insert the values from the entity explicitly.
I've tested this behavior on both the postgres and sqlite providers with the same result. Strangely enough, the model snapshot has the value. I'm using VS Code and the EF global tool
I have a workaround for the behavior, but it's far from ideal:
1. Remove the default value
2. Generate a migration
3. Copy the generated (correct) data insertion statements
4. Remove the migration
5. Add the default value back
6. Paste the correct statements in place of the generated (incorrect) statements
Test code provided below
### Your code
```csharp
// Program.cs
builder.Services.AddDbContext(options =>
options.UseSqlite());
// Test Model
public class TestModel
{
public int Id { get; set; }
public bool IsWorking { get; set; }
}
// Context.cs
public partial class TestContext : DbContext
{
public virtual DbSet TestModels { get; set; }
public TestContext(DbContextOptions options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity(entity =>
{
entity.HasKey(e => e.Id);
entity.ToTable("test_model");
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.IsWorking)
.HasColumnName("is_working")
.HasDefaultValue(true);
entity.HasData(new TestModel()
{
Id = 1,
IsWorking = false,
});
});
}
}
// Migration
public partial class test_sqlite_default_true : Migration
{
///
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "test_model",
columns: table => new
{
id = table.Column(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
is_working = table.Column(type: "INTEGER", nullable: false, defaultValue: true)
},
constraints: table =>
{
table.PrimaryKey("PK_test_model", x => x.id);
});
migrationBuilder.InsertData(
table: "test_model",
column: "id",
value: 1);
}
///
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "test_model");
}
}
// Model snapshot
partial class TestContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "9.0.6");
modelBuilder.Entity("TestModel", b =>
{
b.Property("Id")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasColumnName("id");
b.Property("IsWorking")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER")
.HasDefaultValue(true)
.HasColumnName("is_working");
b.HasKey("Id");
b.ToTable("test_model", (string)null);
b.HasData(
new
{
Id = 1,
IsWorking = false
});
});
#pragma warning restore 612, 618
}
}
```
### Stack traces
```text
```
### Verbose output
```text
```
### EF Core version
9.0.3
### Database provider
Microsoft.EntityFrameworkCore.Sqlite; Npgsql.EntityFrameworkCore.PostgreSQL
### Target framework
.NET 9.0; .NET 8.0
### Operating system
Mac
### IDE
VS Code
Contributor guide
Assessment
This issue has not been assessed yet.