Entity Framework 身份为 0 的核心种子数据
Entity Framework Core seed data with an Identity of 0
我正在尝试使用 .HasData
向我的模型添加一些种子数据以填充我的数据库。我在我的数据模型中使用 ID 0 映射到每个 table.
上的未知
当尝试 运行 添加此应用程序时,出现以下错误:
The seed entity for entity type 'DboTable' cannot be added because
there was no value provided for the required property 'Id'.
我假设 EFCore 强制使用 null 值,因为整数 0 等同于 null,但是当我尝试强制使用整数解析时,它仍然会抛出相同的错误。
目前我不确定如何处理这个问题,如有任何建议,我们将不胜感激。
摘自 DbContext.cs
...
entity.HasData(new DboTable()
{
Id = 0, // integer
Label = "UNKNOWN", // string
...
});
...
原来 EF Core 2.1 不支持 PK 值为 0。
不幸的是,任何试图将 0 值用于 PK 的种子数据都必须 运行 使用自定义迁移 SQL 以插入其 PK 0 记录。
参见:https://github.com/aspnet/EntityFrameworkCore/issues/12399
在对 EF Core code and I found this 代码行进行逆向工程后,我创建了一些 "hack" 来 绕过 0 PK 值限制。
这是我截取的扩展代码:
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);
}
}
}
}
您可以在 OnModelCreating
方法中像这样使用它:
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"}
//....
);
//....
}
我正在尝试使用 .HasData
向我的模型添加一些种子数据以填充我的数据库。我在我的数据模型中使用 ID 0 映射到每个 table.
当尝试 运行 添加此应用程序时,出现以下错误:
The seed entity for entity type 'DboTable' cannot be added because there was no value provided for the required property 'Id'.
我假设 EFCore 强制使用 null 值,因为整数 0 等同于 null,但是当我尝试强制使用整数解析时,它仍然会抛出相同的错误。
目前我不确定如何处理这个问题,如有任何建议,我们将不胜感激。
摘自 DbContext.cs
...
entity.HasData(new DboTable()
{
Id = 0, // integer
Label = "UNKNOWN", // string
...
});
...
原来 EF Core 2.1 不支持 PK 值为 0。
不幸的是,任何试图将 0 值用于 PK 的种子数据都必须 运行 使用自定义迁移 SQL 以插入其 PK 0 记录。
参见:https://github.com/aspnet/EntityFrameworkCore/issues/12399
在对 EF Core code and I found this 代码行进行逆向工程后,我创建了一些 "hack" 来 绕过 0 PK 值限制。
这是我截取的扩展代码:
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);
}
}
}
}
您可以在 OnModelCreating
方法中像这样使用它:
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"}
//....
);
//....
}