The seed entity for entity type 'X' cannot be added because the was no value provided for the required property “..ID”

半世苍凉 提交于 2020-04-12 19:02:02

问题


I'm playing wit EF Core 2.1 Preview 2. I have troubles with HasData (Seed) method in OnModelCreating(ModelBuilder modelBuilder)

My model is simple POCO class that has no annotation.

public class Tenant {
    public int TenantID {get; set;}
    public string Name {get; set;}
}

in my DbContext inside OnModelCreating method is DB model defined as

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);
}

and the seed mehod is defined as:

modelBuilder.Entity<Tenant>().HasData(new []{
   new Tenant {
      TenantID = 0,
      Name = "SystemTenant",
   }
});

During startap, when ctx.Database.Migrate() is run, I got exception: The seed entity for entity type 'Tenant' cannot be added because there was no value provided for the required property 'TenantID


回答1:


The exception is little bit misleading. There must be some mechanism inside, that tests required properties so they must be different to a default values.

The only change I had to do was specifying TenantID != 0.

modelBuilder.Entity<Tenant>().HasData(new []{ 
   new Tenant {
      TenantID = 1, // Must be != 0
      Name = "SystemTenant",
   }
});



回答2:


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. Related to @Tomino answer. 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"}
        //....
        );

    //....
}



回答3:


I was using a custom service to pull data to database, I did it like this:

builder.Entity<EntityName>().HasData(someSerive.GetById(id).AsEnumerable());

I got to change it to ToArray():

builder.Entity<EntityName>().HasData(someSerive.GetById(id).ToArray());



来源:https://stackoverflow.com/questions/50010613/the-seed-entity-for-entity-type-x-cannot-be-added-because-the-was-no-value-pro

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!