私はウィットをプレイしていますEF Core 2.1 Preview 2。 OnModelCreating(ModelBuilder modelBuilder)
のHasData(シード)メソッドに問題があります
私のモデルは、注釈のない単純なPOCOクラスです。
public class Tenant {
public int TenantID {get; set;}
public string Name {get; set;}
}
私のDbContext
内部のOnModelCreating
メソッドは、次のように定義されたDBモデルです。
modelBuilder.Entity<Tenant>(e => {
e.HasKey(m => m.TenantID)
.HasName("PK_Tenants");
e.Property(m => m.TenantID)
.UseSqlServerIdentityColumn();
e.Property(m => m.Name)
.IsRequired()
.HasMaxLength(256);
}
シードメソッドは次のように定義されます。
modelBuilder.Entity<Tenant>().HasData(new []{
new Tenant {
TenantID = 0,
Name = "SystemTenant",
}
});
Startap中にctx.Database.Migrate()を実行すると、例外が発生しました:エンティティタイプ 'Tenant'のシードエンティティは、必要なプロパティ 'TenantIDに値が指定されていなかったため、追加できません
例外は少し誤解を招くものです。内部には何らかのメカニズムが必要で、必要なプロパティをテストするため、デフォルト値とは異なる必要があります。
私がしなければならない唯一の変更は、TenantID != 0
。
modelBuilder.Entity<Tenant>().HasData(new []{
new Tenant {
TenantID = 1, // Must be != 0
Name = "SystemTenant",
}
});
EF Core コードをリバースエンジニアリングした後、バイパス0 PK値制限に少し「ハック」を作成しましたが、見つかりました- this コードの行。 @ Tomino に関連しています。これが私の切り取った拡張コードです:
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"}
//....
);
//....
}
カスタムサービスを使用してデータをデータベースにプルしていましたが、次のようにしました。
builder.Entity<EntityName>().HasData(someSerive.GetById(id).AsEnumerable());
私はそれをToArray()
に変更しなければなりません:
builder.Entity<EntityName>().HasData(someSerive.GetById(id).ToArray());