3

I am trying to seed a OneToMany Relationship in my Database with defined List<> and I get the following Error-Msg

'The seed entity for entity type 'Country' cannot be added because it has the navigation 'WineRegions' set. To seed relationships you need to add the related entity seed to 'WineRegion' and specify the foreign key values {'CountryId'}. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the involved property values.'

I used this page to create my classes: https://www.learnentityframeworkcore.com/relationships#one-to-many ... I can only guess that I somehow need to define the keys manually even though it should work automatically...

Here are my two classes. WineRegions contains one Country and Country contains a collection of 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; }
}

During the Seeding I don't want to use hardcoded Objects like (btw this code works...):

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

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

As I mentioned before I want to use List which I generate during a JSON Parsing process.

So this is what I do:

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

My JSON looks like this:

  "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
bkDev
  • 66
  • 5

2 Answers2

2

Your WineRegionId and ConutryId are Identity and it generated automatically by SQL.

When your database keys are identity Id = 1 doesn't work.

You Should remove identity from CountryId and WineRegionId.

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

Another way

You can change your code to this.

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

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

in this case ConutryId and WineRegionId generated automatically by SQL and relations between Conutry and WineRegion created by this line

new { Name = "Bordeaux", Country = country/*<--NOTE THIS*/ }
Farhad Zamani
  • 5,381
  • 2
  • 16
  • 41
  • thanks for the quick response! I changed the Id columns of both models in the way you recommended. Now I am getting the error: The seed entity for entity type 'WineRegion' cannot be added because it has the navigation 'Country' set. To seed relationships you need to add the related entity seed to 'Country' and specify the foreign key values {'CountryId'}. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the involved property values. – bkDev Jun 14 '20 at 13:23
  • @bkDev Do you checked the state of identity `Id` after changing the identity state columns to `None` in `sql`? identity should be disabled after changing. – Farhad Zamani Jun 14 '20 at 14:32
  • How do I check this? I tried a couple of things and I found out that the country part works as long as I delete the WineRegion part. That means that I have Countries in my Countries-Table :). Now I need to find out why the wineRegion parts is still crashing – bkDev Jun 14 '20 at 15:36
  • @bkDev You can check this in `SQL Server`. right click on your table and select **Design**. then select the `Id` field then in `Column Properties` and set `Identity Specification` to **No** . This [link](https://stackoverflow.com/a/1234789/7086678) maybe helpful for you to disable identity – Farhad Zamani Jun 14 '20 at 16:18
  • @bkDev Remember that when you edit your model you should use `Add-Migration` and `Update-database` – Farhad Zamani Jun 14 '20 at 16:21
  • Yes. I disabled the seeding and used `Add-Migration` and `Update-database` before I filled the country table. – bkDev Jun 15 '20 at 05:28
  • The table looks like this `CREATE TABLE [dbo].[Countries] ( [ISO3166Alpha2] NVARCHAR (2) NOT NULL, [CountryId] INT DEFAULT ((0)) NOT NULL, [CountryName] NVARCHAR (255) DEFAULT (N'') NOT NULL, CONSTRAINT [PK_Countries] PRIMARY KEY CLUSTERED ([CountryId] ASC) ); ` – bkDev Jun 15 '20 at 05:29
  • Regions like this: `CREATE TABLE [dbo].[WineRegions] ( [CountryId] INT NULL, [WineRegionId] INT DEFAULT ((0)) NOT NULL, [WineRegionName] NVARCHAR (MAX) NULL, CONSTRAINT [PK_WineRegions] PRIMARY KEY CLUSTERED ([WineRegionId] ASC), CONSTRAINT [FK_WineRegions_Countries_CountryId] FOREIGN KEY ([CountryId]) REFERENCES [dbo].[Countries] ([CountryId]) ); GO CREATE NONCLUSTERED INDEX [IX_WineRegions_CountryId] ON [dbo].[WineRegions]([CountryId] ASC);` – bkDev Jun 15 '20 at 05:30
1

So i figured out how to fix it but I don't exactly understand why it has to be like this... A big "thank you" to Farhad Zamani!

  1. I changed the identity attribute to: [DatabaseGenerated(DatabaseGeneratedOption.None)] -
  2. I needed to remove the [Key] Attributes from both classes
  3. I needed to apply the [NotMapped] attribute to the nested class Country within the WineRegion class
  4. I needed to apply the ForeignKey Attribute to CountryId property.

    public class WineRegion
    {
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int WineRegionId { get; set; }
    
    public string WineRegionName { get; set; }
    
    [NotMapped]
    public Country Country { get; set; }
    
    [ForeignKey("CountryId")]
    public int CountryId { get; set; }
    }
    
    public class Country
    {
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int CountryId { get; set; }
    
    [Required]
    [MaxLength(255)]
    public string CountryName { get; set; }
    
    [Required]
    [MaxLength(2)]
    public string ISO3166Alpha2 { get; set; }
    
    public List<WineRegion> WineRegions { get; set; }
    }
    
bkDev
  • 66
  • 5