I'm trying to add some seed data to my model using .HasData
in order to populate my database. I use ID 0 within my data model to map to unknown on each table.
When trying to run the application once adding this, I get the following error:
The seed entity for entity type 'DboTable' cannot be added because there was no value provided for the required property 'Id'.
I assumed that EFCore forces a value of null since a integer of 0 is equivalent to null, but when I try to force an integer parse, it still throws the same error.
At this point I'm unsure of how to approach this, any advice would be appreciated.
snippit from DbContext.cs
...
entity.HasData(new DboTable()
{
Id = 0, // integer
Label = "UNKNOWN", // string
...
});
...
Turns out that EF Core 2.1 doesn't support a PK value of 0.
Unfortunately, any seed data trying to use a value of 0 for a PK will have to run a migration with custom SQL to insert their PK 0 records.
see: https://github.com/aspnet/EntityFrameworkCore/issues/12399
I have created little "hack" to bypass 0 PK value restriction after I reverse engineering the EF Core code and I found this line of code.
Here is my snipped extension code:
using System;
using System.Linq;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
namespace EntityFrameworkCore.CustomMigration
{
public static class CustomModelBuilder
{
public static bool IsSignedInteger(this Type type)
=> type == typeof(int)
|| type == typeof(long)
|| type == typeof(short)
|| type == typeof(sbyte);
public static void Seed<T>(this ModelBuilder modelBuilder, IEnumerable<T> data) where T : class
{
var entnty = modelBuilder.Entity<T>();
var pk = entnty.Metadata
.GetProperties()
.FirstOrDefault(property =>
property.RequiresValueGenerator()
&& property.IsPrimaryKey()
&& property.ClrType.IsSignedInteger()
&& property.ClrType.IsDefaultValue(0)
);
if (pk != null)
{
entnty.Property(pk.Name).ValueGeneratedNever();
entnty.HasData(data);
entnty.Property(pk.Name).UseSqlServerIdentityColumn();
}
else
{
entnty.HasData(data);
}
}
}
}
And you can use it like this in OnModelCreating
method:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Seed(new List<Tenant> {
new Tenant() {TenantID = 0 , Name = string.Empty},
new Tenant() {TenantID = 1 , Name = "test"}
//....
);
//....
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With