首页 > 解决方案 > EF Core 种子数据库 OneToMany 与预定义列表的关系

问题描述

我正在尝试使用已定义的 List<> 在我的数据库中播种 OneToMany 关系,我收到以下错误消息

'无法添加实体类型'Country'的种子实体,因为它设置了导航'WineRegions'。要为关系播种,您需要将相关实体种子添加到“WineRegion”并指定外键值 {'CountryId'}。考虑使用“DbContextOptionsBuilder.EnableSensitiveDataLogging”来查看所涉及的属性值。

我使用此页面创建我的课程: https ://www.learnentityframeworkcore.com/relationships#one-to-many ...我只能猜测我需要手动定义键,即使它应该自动工作.. .

这是我的两节课。WineRegions 包含一个 Country 和 Country 包含 WineRegions 的集合:

public class WineRegion
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int WineRegionId { get; set; }

    public string WineRegionName { get; set; }   

    public int CountryId { get; set; }
    public Country Country { get; set; }
}

public class Country
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CountryId { get; set; }

    [Required]
    [MaxLength(255)]
    public string CountryName { get; set; }

    [Required]
    [MaxLength(2)]
    public string ISO3166Alpha2 { get; set; }

    public ICollection<WineRegion> WineRegions { get; set; }
}

在播种期间,我不想使用硬编码的对象,例如(顺便说一句,此代码有效......):

        modelBuilder.Entity<Country>().HasData(
            new { Id = 1, Name = "France", ISO3166Alpha2 = "FR" }
            );

        modelBuilder.Entity<WineRegion>().HasData(
            new { Id = 1, Name = "Bordeaux", CountryId = 1 }
            );

正如我之前提到的,我想使用在 JSON 解析过程中生成的 List。

所以这就是我所做的:

        modelBuilder.Entity<Country>().HasData(listOfCountries);  // List<Country>
        modelBuilder.Entity<WineRegion>().HasData(listOfWineRegions); //List<WineRegion>

我的 JSON 看起来像这样:

  "wineregions": [
    {
      "id": 1,
      "country": "France",
      "iso2": "FR",
      "region": [
        {
          "id": 1,
          "name": "Bordeaux"
        },
        {
          "id": 2,
          "name": "Burgundy"
        },
        {
          "id": 4,
          "name": "Burgundy"
        },
        {
          "id": 5,
          "name": "Beaujolais"
        },
        {
          "id": 6,
          "name": "Champagne"
        },
        {
          "id": 7,
          "name": "Loire"
        },
        {
          "id": 8,
          "name": "Alsace"
        },
        {
          "id": 9,
          "name": "Rhône"
        },
        {
          "id": 10,
          "name": "Provence"
        },
        {
          "id": 11,
          "name": "Languedoc-Roussillon"
        },
        {
          "id": 12,
          "name": "Jura"
        }
      ]
    },
    {
      "id": 2,
      "country": "Italy",
      "iso2": "IT",
      "region": [
        {
          "id": 1,
          "name": "Piedmont"
        },
        {
          "id": 2,
          "name": "Barolo"
        },
        {
          "id": 3,
          "name": "Barbaresco"
        },
        {
          "id": 4,
          "name": "Tuscany"
        },
        {
          "id": 5,
          "name": "Veneto"
        },
        {
          "id": 6,
          "name": "Friuli-Venezia"
        },
        {
          "id": 7,
          "name": "Giulia"
        },
        {
          "id": 8,
          "name": "Abruzzo"
        },
        {
          "id": 9,
          "name": "Sicily"
        },
        {
          "id": 10,
          "name": "Lambrusco"
        }
      ]
    }
  ]
} 


Thanks in advance

标签: c#asp.netone-to-manyseedingef-core-3.0

解决方案


WineRegionIdConutryId是身份,它由 SQL 自动生成。

当您的数据库密钥是身份时Id = 1 ,它不起作用。

CountryId您应该从和中删除身份WineRegionId

[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int CountryId { get; set; }
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int WineRegionId { get; set; }

另一种方式

您可以将代码更改为此。

Country country = new Country { Name = "France", ISO3166Alpha2 = "FR" };
modelBuilder.Entity<Country>().HasData(country);

modelBuilder.Entity<WineRegion>().HasData(
            new { Name = "Bordeaux", Country = country }
            );

在这种情况下ConutryId,由这条线WineRegionId自动生成SQL和之间的关系Conutry并由WineRegion这条线创建

new { Name = "Bordeaux", Country = country/*<--NOTE THIS*/ }

推荐阅读