Skip to content

Commit 080e108

Browse files
authored
Don't assume that FK of skip navigation is non-null (#32920)
* Don't assume that FK of skip navigation is non-null Fixes #32732 * Add additional assesion.
1 parent 31bd863 commit 080e108

File tree

2 files changed

+43
-1
lines changed

2 files changed

+43
-1
lines changed

src/EFCore.SqlServer/Metadata/Conventions/SqlServerOnDeleteConvention.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ protected override DeleteBehavior GetTargetDeleteBehavior(IConventionForeignKey
6868
s => s.Inverse != null
6969
&& IsMappedToSameTable(s.DeclaringEntityType, s.TargetEntityType));
7070

71-
if (skipNavigation != null)
71+
if (skipNavigation != null
72+
&& skipNavigation.ForeignKey != null)
7273
{
7374
var isFirstSkipNavigation = IsFirstSkipNavigation(skipNavigation);
7475
if (!isFirstSkipNavigation)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
namespace Microsoft.EntityFrameworkCore.Metadata.Conventions;
5+
6+
public class SqlServerOnDeleteConventionTest
7+
{
8+
[ConditionalFact] // Issue #32732
9+
public void Convention_does_not_assume_skip_navigations_have_non_null_FK()
10+
{
11+
using var context = new SkippyDbContext();
12+
var model = context.Model;
13+
Assert.Equal(["ArenaPropensity", "Arena", "Propensity"], model.GetEntityTypes().Select(e => e.ShortName()));
14+
Assert.Equal(
15+
[DeleteBehavior.Cascade, DeleteBehavior.ClientCascade],
16+
model.GetEntityTypes().Single(e => e.ShortName() == "ArenaPropensity").GetForeignKeys().Select(k => k.DeleteBehavior));
17+
}
18+
19+
public class SkippyDbContext : DbContext
20+
{
21+
public DbSet<Arena> Areas { get; private set; }
22+
23+
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
24+
=> optionsBuilder.UseSqlServer();
25+
}
26+
27+
public class Arena : Propensity
28+
{
29+
public virtual ICollection<Propensity> AreaProperties { get; set; }
30+
}
31+
32+
public abstract class Propensity
33+
{
34+
public int Id { get; set; }
35+
36+
public int? PrimaryYId { get; set; }
37+
public virtual Propensity PrimaryYProp { get; set; }
38+
39+
public virtual ICollection<Arena> PropertyAreas { get; set; }
40+
}
41+
}

0 commit comments

Comments
 (0)