Начальный объект для типа объекта «X» не может быть добавлен, поскольку для обязательного свойства «..ID» не было предоставлено значение - PullRequest
0 голосов
/ 24 апреля 2018

Я играю с EF Core 2.1 Preview 2 . У меня проблемы с методом HasData (Seed) в OnModelCreating(ModelBuilder modelBuilder)

Моя модель - простой класс POCO, у которого нет аннотации.

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

в моем методе DbContext inside OnModelCreating модель БД определяется как

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

Во время стартапа, когда запускается ctx.Database.Migrate (), я получил исключение: Начальный объект для типа объекта «Арендатор» не может быть добавлен, поскольку для требуемого свойства «TenantID

не было предоставлено значение»

Ответы [ 3 ]

0 голосов
/ 11 марта 2019

Я использовал пользовательский сервис для извлечения данных в базу данных, я сделал это так:

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

Я должен изменить его на ToArray():

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

0 голосов
/ 19 июня 2019

Я создал небольшой "хак" для обхода ограничения значения 0 PK после того, как я пересмотрел код EF Core и нашел эту строку кода. Относится к @ 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"}
        //....
        );

    //....
}
0 голосов
/ 24 апреля 2018

Исключение немного вводит в заблуждение. Внутри должен быть какой-то механизм, который проверяет требуемые свойства, поэтому они должны отличаться от значений по умолчанию.

Единственное изменение, которое я должен был сделать, это указать TenantID != 0.

modelBuilder.Entity<Tenant>().HasData(new []{ 
   new Tenant {
      TenantID = 1, // Must be != 0
      Name = "SystemTenant",
   }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...