【问题标题】:Entity Framework Core seed data with an Identity of 0标识为 0 的 Entity Framework Core 种子数据
【发布时间】:2019-06-19 14:23:37
【问题描述】:

我正在尝试使用.HasData 将一些种子数据添加到我的模型中,以填充我的数据库。我在我的数据模型中使用 ID 0 映射到每个表上的未知数。

添加后尝试运行应用程序时,出现以下错误:

无法添加实体类型“DboTable”的种子实体,因为 没有为所需的属性“Id”提供值。

我假设 EFCore 强制使用 null 值,因为整数 0 等效于 null,但是当我尝试强制进行整数解析时,它仍然会抛出相同的错误。

目前我不确定如何处理这个问题,任何建议都将不胜感激。

来自 DbContext.cs 的片段

...
entity.HasData(new DboTable()
{
    Id = 0,               // integer
    Label = "UNKNOWN",    // string
    ...
});
...

【问题讨论】:

    标签: asp.net-core ef-core-2.1


    【解决方案1】:

    原来 EF Core 2.1 不支持 PK 值 0。

    不幸的是,任何尝试对 PK 使用 0 值的种子数据都必须使用自定义 SQL 运行迁移以插入其 PK 0 记录。

    见:https://github.com/aspnet/EntityFrameworkCore/issues/12399

    【讨论】:

      【解决方案2】:

      在我对 EF Core 代码进行逆向工程并找到 this 代码行之后,我创建了一个小“黑客”来绕过 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"}
              //....
              );
      
          //....
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-07
        • 2021-06-30
        • 2016-05-14
        • 1970-01-01
        • 1970-01-01
        • 2018-12-04
        相关资源
        最近更新 更多