Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

foreign key generation not working on 7.x builds, works on 6.x #28392

Closed
WillEhrendreich opened this issue Jul 8, 2022 · 1 comment · Fixed by #29026
Closed

foreign key generation not working on 7.x builds, works on 6.x #28392

WillEhrendreich opened this issue Jul 8, 2022 · 1 comment · Fixed by #29026
Labels
area-save-changes closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Milestone

Comments

@WillEhrendreich
Copy link

WillEhrendreich commented Jul 8, 2022

I have 2 classes that correlate to 2 tables.

for simplicity i'll repro the smallest possible versions.

Class one, which has the bulk of the data is created by the ERP software I'm writing an application against. We'll call it MainRow.

Class two we'll call Extension, because it's from a table that was created by another third party developer, not the same as the company that created the table for MainRow. The third party software uses this extension table to tack on extra data later as part of a separate but integrated application to use with the ERP software, without changing the MainRow that the ERP software has.

  public class MainRow
  {
    private int _identityColumn;
    [Key]
    public int IdentityColumn
    {
      get
      {
        AssignMainRowToID();
        return _identityColumn;
      }
      set
      {
        AssignMainRowToID();
        _identityColumn = value;
      }
    }
    [NotMapped]
    public Extension Ext { get; set; } = new();

    [NotMapped]
    public int MainRowKey { get => AssignMainRowToID(); set => Ext.MainRowKey = value; }

    private int AssignMainRowToID()
    {
      Ext.MainRowKey =_identityColumn;
      return Ext.MainRowKey;
    }
  }

 public class Extension
  {
    [NotMapped]   
    public MainRow Main{ get; set; }
    public long IdentityColumn { get; set; }
    public int MainRowKey { get; set; }
  }
 

I have the main row configured with this one to one relationship:

      entity.HasOne(x => x.Ext)
        .WithOne(x => x.Main)
        .HasForeignKey<Extension>(x => x.MainRowKey)
        .IsRequired();

The extension table was created with Int64 as the foreign key, which references the Identity Column of the Main Row.. because... I guess... whoever created it likes adding unnecessary challenges in life.. or something..

Anyway, I have no ability to change the data type of the FK on the server, so I have to do a conversion which i do like this:

// extension class configuration 

      entity.Property(e => e.MainRowKey)
      .ValueGeneratedNever()
      .HasColumnType("bigint")
      .HasColumnName("FKey_ID");

This conversion works fine in 6, not in 7.

in any 7 version I've tried get this:

""System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.InvalidCastException: Unable to cast object of type 'Microsoft.EntityFrameworkCore.Update.Internal.SimpleRowKeyValueFactory`1[System.Int32]' to type 'Microsoft.EntityFrameworkCore.Update.Internal.IRowKeyValueFactory`1[System.Int64]'.
   at Microsoft.EntityFrameworkCore.Update.Internal.RowForeignKeyValueFactory`1..ctor(IForeignKeyConstraint foreignKey)
   at Microsoft.EntityFrameworkCore.Update.Internal.SimpleNonNullableRowForeignKeyValueFactory`1..ctor(IForeignKeyConstraint foreignKey, IColumn column, ColumnAccessors columnAccessors)
   at Microsoft.EntityFrameworkCore.Update.Internal.RowForeignKeyValueFactoryFactory.CreateSimple[TKey](IForeignKeyConstraint foreignKey)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Microsoft.EntityFrameworkCore.Update.Internal.RowForeignKeyValueFactoryFactory.Create(IForeignKeyConstraint foreignKey)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKeyConstraint.<>c.<GetRowForeignKeyValueFactory>b__28_0(ForeignKeyConstraint constraint)
   at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKeyConstraint.GetRowForeignKeyValueFactory()
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.AddForeignKeyEdges(Multigraph`2 commandGraph)
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.TopologicalSort(IEnumerable`1 commands)
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.BatchCommands(IList`1 entries, IUpdateAdapter updateAdapter)+MoveNext()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(StateManager stateManager, Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<>c.<SaveChanges>b__104_0(DbContext _, ValueTuple`2 t)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass28_0`2.<Execute>b__0(DbContext context, TState state)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementation[TState,TResult](Func`3 operation, Func`3 verifySucceeded, TState state)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)"
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.InvalidCastException: Unable to cast object of type 'Microsoft.EntityFrameworkCore.Update.Internal.SimpleRowKeyValueFactory`1[System.Int32]' to type 'Microsoft.EntityFrameworkCore.Update.Internal.IRowKeyValueFactory`1[System.Int64]'.
   at Microsoft.EntityFrameworkCore.Update.Internal.RowForeignKeyValueFactory`1..ctor(IForeignKeyConstraint foreignKey)
   at Microsoft.EntityFrameworkCore.Update.Internal.SimpleNonNullableRowForeignKeyValueFactory`1..ctor(IForeignKeyConstraint foreignKey, IColumn column, ColumnAccessors columnAccessors)
   at Microsoft.EntityFrameworkCore.Update.Internal.RowForeignKeyValueFactoryFactory.CreateSimple[TKey](IForeignKeyConstraint foreignKey)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Microsoft.EntityFrameworkCore.Update.Internal.RowForeignKeyValueFactoryFactory.Create(IForeignKeyConstraint foreignKey)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKeyConstraint.<>c.<GetRowForeignKeyValueFactory>b__28_0(ForeignKeyConstraint constraint)
   at Microsoft.EntityFrameworkCore.Internal.NonCapturingLazyInitializer.EnsureInitialized[TParam,TValue](TValue& target, TParam param, Func`2 valueFactory)
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKeyConstraint.GetRowForeignKeyValueFactory()
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.AddForeignKeyEdges(Multigraph`2 commandGraph)
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.TopologicalSort(IEnumerable`1 commands)
   at Microsoft.EntityFrameworkCore.Update.Internal.CommandBatchPreparer.BatchCommands(IList`1 entries, IUpdateAdapter updateAdapter)+MoveNext()
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable`1 commandBatches, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Storage.RelationalDatabase.SaveChanges(IList`1 entries)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IList`1 entriesToSave)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(StateManager stateManager, Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<>c.<SaveChanges>b__104_0(DbContext _, ValueTuple`2 t)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass28_0`2.<Execute>b__0(DbContext context, TState state)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementation[TState,TResult](Func`3 operation, Func`3 verifySucceeded, TState state)
   at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)


EF Core version: 6.0.0 and 7.0.0-preview.5.22302.2
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework:  .NET 6.0
Operating system: Windows
IDE: Visual Studio 2022 17.3 preview 2
@ajcvickers
Copy link
Member

Note from triage: likely due to use of store types for comparisons in the update pipeline.

@ajcvickers ajcvickers self-assigned this Sep 2, 2022
ajcvickers added a commit that referenced this issue Sep 9, 2022
Approach uses built-in value converters to convert FK value to type of PK.

Fixes #28392
@ajcvickers ajcvickers added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Sep 9, 2022
ajcvickers added a commit that referenced this issue Sep 9, 2022
Approach uses built-in value converters to convert FK value to type of PK.

Fixes #28392
ajcvickers added a commit that referenced this issue Sep 9, 2022
Approach uses built-in value converters to convert FK value to type of PK.

Fixes #28392
@ajcvickers ajcvickers modified the milestones: 7.0.0, 7.0.0-rc2 Sep 10, 2022
@ajcvickers ajcvickers modified the milestones: 7.0.0-rc2, 7.0.0 Nov 5, 2022
@ajcvickers ajcvickers removed their assignment Aug 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-save-changes closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported regression type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants