Efcore: Creating a data seed migration with both Principal and Dependent entity at the same time causes an error

Created on 18 Mar 2020  路  5Comments  路  Source: dotnet/efcore


Given the following context with the following CascadeTiming settings and the model:

```C#
public BloggingContext() : base()
{
ChangeTracker.CascadeDeleteTiming = CascadeTiming.OnSaveChanges;
ChangeTracker.DeleteOrphansTiming = CascadeTiming.OnSaveChanges;
}

public class LookupType
{
    public Guid LookupTypeId { get; set; }
    public string TypeName { get; set; }
    public ICollection<LookupCode> LookupCodes { get; set; }
}

public class LookupCode
{
    public Guid LookupCodeId { get; set; }
    public LookupType LookupType { get; set; }
    public Guid LookupTypeId { get; set; }
    public string Code { get; set; }
}

With the following configuration:
```C#
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<LookupType>().HasKey(x => x.LookupTypeId);
            modelBuilder.Entity<LookupCode>().HasKey(x => x.LookupCodeId);
            modelBuilder.Entity<LookupCode>()
                .HasOne(x => x.LookupType)
                .WithMany(x => x.LookupCodes)
                .HasForeignKey(x => x.LookupTypeId)
                .OnDelete(DeleteBehavior.Restrict);
        }

And the following seed method that contains both the principal and dependent entity:
```C#
private void SeedData(ModelBuilder builder)
{
builder.Entity().HasData(
new LookupType
{
LookupTypeId = new Guid("d3046cf1-61b0-4748-8373-157907404d49"),
TypeName = "Test"
}
);

        builder.Entity<LookupCode>().HasData(
            new LookupCode
            {
                LookupCodeId = new Guid("97081e59-09cd-4bab-849b-586b98f6134d"),
                LookupTypeId = new Guid("d3046cf1-61b0-4748-8373-157907404d49"),
                Code = "Test Code"
            }
        );
    }

If you try to create a Code First migration, this gives the following error:

The association between entities 'LookupType' and 'LookupCode' with the key value '{LookupTypeId: d3046cf1-61b0-4748-8373-157907404d49}' has been severed but the relationship is either marked as 'Required' or is implicitly required because the foreign key is not nullable. If the dependent/child entity should be deleted when a required relationship is severed, then setup the relationship to use cascade deletes.


Note that this is a perfectly valid case for data seeding. This works without any problems in EF Core 2.x

### Steps to reproduce

Attached is a small reproducible sample:

[DataSeeding Issue.zip](https://github.com/dotnet/efcore/files/4346515/DataSeeding.Issue.zip)

Just go into `ConsoleApp6\ConsoleApp6` and run `dotnet-ef migrations add name`

--verbose flag output
```C#
PS C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6> dotnet-ef migrations add TEST1 --verbose
Using project 'C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\ConsoleApp6.csproj'.
Using startup project 'C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\ConsoleApp6.csproj'.
Writing 'C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\obj\ConsoleApp6.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\l46ko\AppData\Local\Temp\tmpFE2.tmp /verbosity:quiet /nologo C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\ConsoleApp6.csproj
Writing 'C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\obj\ConsoleApp6.csproj.EntityFrameworkCore.targets'...
dotnet msbuild /target:GetEFProjectMetadata /property:EFProjectMetadataFile=C:\Users\l46ko\AppData\Local\Temp\tmp1206.tmp /verbosity:quiet /nologo C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\ConsoleApp6.csproj
Build started...
dotnet build C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\ConsoleApp6.csproj /verbosity:quiet /nologo

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.88
Build succeeded.
dotnet exec --depsfile C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\bin\Debug\netcoreapp3.1\ConsoleApp6.deps.json --additionalprobingpath C:\Users\l46ko\.nuget\packages --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\bin\Debug\netcoreapp3.1\ConsoleApp6.runtimeconfig.json C:\Users\l46ko\.dotnet\tools\.store\dotnet-ef\3.1.1\dotnet-ef\3.1.1\tools\netcoreapp3.1\any\tools\netcoreapp2.0\any\ef.dll migrations add TEST1 --assembly C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\bin\Debug\netcoreapp3.1\ConsoleApp6.dll --startup-assembly C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\bin\Debug\netcoreapp3.1\ConsoleApp6.dll --project-dir C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\ --language C# --working-dir C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6 --verbose --root-namespace ConsoleApp6
Using assembly 'ConsoleApp6'.
Using startup assembly 'ConsoleApp6'.
Using application base 'C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\bin\Debug\netcoreapp3.1'.
Using working directory 'C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6'.
Using root namespace 'ConsoleApp6'.
Using project directory 'C:\Users\l46ko\Desktop\ConsoleApp6\ConsoleApp6\'.
The EF Core tools version '3.1.1' is older than that of the runtime '3.1.2'. Update the tools for the latest features and bug fixes.
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Finding application service provider...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'BloggingContext'.
Created Context
Using context 'BloggingContext'.
Finding design-time services for provider 'Microsoft.EntityFrameworkCore.Sqlite'...
Using design-time services from provider 'Microsoft.EntityFrameworkCore.Sqlite'.
Finding design-time services referenced by assembly 'ConsoleApp6'.
No referenced design-time services were found.
Finding IDesignTimeServices implementations in assembly 'ConsoleApp6'...
No design-time services were found.
Context 'BloggingContext' started tracking 'LookupCode' entity with key '{LookupCodeId: 97081e59-09cd-4bab-849b-586b98f6134d}'.
Context 'BloggingContext' started tracking 'LookupType' entity with key '{LookupTypeId: d3046cf1-61b0-4748-8373-157907404d49}'.
DetectChanges starting for 'BloggingContext'.
DetectChanges completed for 'BloggingContext'.
DetectChanges starting for 'BloggingContext'.
DetectChanges completed for 'BloggingContext'.
Context 'BloggingContext' started tracking 'LookupCode' entity with key '{LookupCodeId: 97081e59-09cd-4bab-849b-586b98f6134d}'.
The 'LookupCode' entity with key '{LookupCodeId: 97081e59-09cd-4bab-849b-586b98f6134d}' tracked by 'BloggingContext' changed from 'Added' to 'Unchanged'.
Context 'BloggingContext' started tracking 'LookupType' entity with key '{LookupTypeId: d3046cf1-61b0-4748-8373-157907404d49}'.
The 'LookupType' entity with key '{LookupTypeId: d3046cf1-61b0-4748-8373-157907404d49}' tracked by 'BloggingContext' changed from 'Added' to 'Unchanged'.
The 'LookupType' entity with key '{LookupTypeId: d3046cf1-61b0-4748-8373-157907404d49}' tracked by 'BloggingContext' changed from 'Unchanged' to 'Deleted'.
The 'LookupCode' entity with key '{LookupCodeId: 97081e59-09cd-4bab-849b-586b98f6134d}' tracked by 'BloggingContext' changed from 'Unchanged' to 'Modified'.
'BloggingContext' disposed.
System.InvalidOperationException: The association between entities 'LookupType' and 'LookupCode' with the key value '{LookupTypeId: d3046cf1-61b0-4748-8373-157907404d49}' has been severed but the relationship is either marked as 'Required' or is implicitly required because the foreign key is not nullable. If the dependent/child entity should be deleted when a required relationship is severed, then setup the relationship to use cascade deletes.
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.HandleConceptualNulls(Boolean sensitiveLoggingEnabled, Boolean force, Boolean isCascadeDelete)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.CascadeDelete(InternalEntityEntry entry, Boolean force, IEnumerable`1 foreignKeys)
   at Microsoft.EntityFrameworkCore.Update.Internal.UpdateAdapter.CascadeDelete(IUpdateEntry entry, IEnumerable`1 foreignKeys)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDataOperations(DiffContext diffContext)+MoveNext()
   at System.Linq.Enumerable.ConcatIterator`1.MoveNext()
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.Sort(IEnumerable`1 operations, DiffContext diffContext)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationsModelDiffer.GetDifferences(IModel source, IModel target)
   at Microsoft.EntityFrameworkCore.Migrations.Design.MigrationsScaffolder.ScaffoldMigration(String migrationName, String rootNamespace, String subNamespace, String language)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
The association between entities 'LookupType' and 'LookupCode' with the key value '{LookupTypeId: d3046cf1-61b0-4748-8373-157907404d49}' has been severed but the relationship is either marked as 'Required' or is implicitly required because the foreign key is not nullable. If the dependent/child entity should be deleted when a required relationship is severed, then setup the relationship to use cascade deletes.

Further technical details

EF Core version: 3.1.1
EF Core tools: 3.1.1
Target framework: .NET Core 3.0

closed-fixed customer-reported type-bug

Most helpful comment

Verified that this is fixed in EF Core 5.0 preview 5,

All 5 comments

Note for team: I was able to reproduce this, but only with the generated migration already in the project. So this looks like it's happening only when adding seed data in a second migration after creating the database structure in the first migration.

I'd love to hear any suggestions on workarounds, other than changing the DeleteBehavior on those foreign keys.

Verified that this is fixed in EF Core 5.0 preview 5,

I ran into this, got really excited that it was fixed, then realized it's not coming until EF Core 5.0. Are there no workarounds in the meantime? Having to seed the data in the same migrations the schema is created is the best we can do for now?

Ran into this problem, Googled for solutions and find this post, by someone that works at my company. My codebase is derived from his. I also got excited, then disappointed.

Was this page helpful?
0 / 5 - 0 ratings