dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.74k stars 3.18k forks source link

Fluent API HasForeignKey Breaking Change from 2.1 to 2.2 #14158

Closed danstur closed 5 years ago

danstur commented 5 years ago

There's a breaking change between EF Core 2.1 and 2.2.

It seemed easier to create a quick repo with a minimal example that demonstrates the issue than to inline all the code here. See this repository. If that's problematic for some reason, I can certainly also upload the code directly here.

The issue seems to stem from shadow properties in combination with HasForeignKey.

Steps to reproduce

  1. git clone https://github.com/danstur/EfCoreBreakingChange.git
  2. Execute CreateDb.sql on SQL Server 2017 (the real issue occurs at least on 2016 as well, but I only tested the minimal sample on my 2017 install - probably DB independent).
  3. adapt connectionstring in Program.cs:12 as required
  4. execute program ==> no exceptions, everything ok.
  5. Update to 2.2 EF Core NuGets and rebuild to make sure nugets are switched.
  6. Execute Program again. This time an exception occurs.
Message: The relationship from 'OutboundDelivery.Sender' to 'Site' with foreign key properties {'SenderId' : string} cannot target the primary key {'Id' : int} because it is not compatible. Configure a principal key or a set of compatible foreign key properties for this relationship.
Stack Trace:
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.ValidateNoShadowKeys(IModel model)
   at Microsoft.EntityFrameworkCore.Infrastructure.ModelValidator.Validate(IModel model)
   at Microsoft.EntityFrameworkCore.Infrastructure.RelationalModelValidator.Validate(IModel model)
   at Microsoft.EntityFrameworkCore.Internal.SqlServerModelValidator.Validate(IModel model)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ValidatingConvention.Apply(InternalModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.Metadata.Conventions.Internal.ConventionDispatcher.ImmediateConventionScope.OnModelBuilt(InternalModelBuilder modelBuilder)
   at Microsoft.EntityFrameworkCore.ModelBuilder.FinalizeModel()
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.LazyInitValue()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.CreateModel()
   at Microsoft.EntityFrameworkCore.Internal.DbContextServices.get_Model()
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScoped(ScopedCallSite scopedCallSite, ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass1_0.<RealizeService>b__0(ServiceProviderEngineScope scope)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
   at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider)
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
   at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
   at Microsoft.EntityFrameworkCore.DbContext.Set[TEntity]()
   at EfCoreBreakingChange.Program.<Main>d__0.MoveNext() in C:\dev\OpenSourceProjects\EfCoreBreakingChange\EfCoreBreakingChange\Program.cs:line 64
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at EfCoreBreakingChange.Program.<Main>(String[] args)

Workarounds

Further technical details

EF Core version: 2.2 Database Provider: Microsoft.EntityFrameworkCore.SqlServer Operating system: Windows 10 x64 1803 IDE: Visual Studio 2017 15.9.3

AndriySvyryd commented 5 years ago

@danstur Another workaround is to apply SiteTypeConfiguration first.

Unfortunately fixing this in a patch release would be too risky.

AndriySvyryd commented 5 years ago

Seems that we missed this case in https://github.com/aspnet/EntityFrameworkCore/pull/13720