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

StackOverflowException with EFCore 5 many-to-many mapping using many-to-one via self #23377

Closed
FransBouma opened this issue Nov 18, 2020 · 7 comments
Labels
area-model-building closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported Servicing-approved type-bug
Milestone

Comments

@FransBouma
Copy link

FransBouma commented Nov 18, 2020

EF Core version: 5.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 5.0
Operating system: Windows 10
IDE: (e.g. Visual Studio 2019 16.8)

Stacktrace:

long stackoverflow stacktrace

Stack overflow.
at System.Globalization.CompareInfo.IcuCompareString(System.ReadOnlySpan1<Char>, System.ReadOnlySpan1, System.Globalization.CompareOptions)
at System.Globalization.CompareInfo.Compare(System.ReadOnlySpan1<Char>, System.ReadOnlySpan1, System.Globalization.CompareOptions)
at System.Globalization.CompareInfo.Compare(System.String, System.String, System.Globalization.CompareOptions)
at System.String.Compare(System.String, System.String, System.StringComparison)
at System.String.CompareTo(System.String)
at System.Collections.Generic.GenericComparer1[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Compare(System.__Canon, System.__Canon) at System.Collections.Generic.SortedDictionary2+KeyValuePairComparer[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Compare(System.Collections.Generic.KeyValuePair2<System.__Canon,System.__Canon>, System.Collections.Generic.KeyValuePair2<System.__Canon,System.__Canon>)
at System.Collections.Generic.SortedSet1[[System.Collections.Generic.KeyValuePair2[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].FindNode(System.Collections.Generic.KeyValuePair2<System.__Canon,System.__Canon>) at System.Collections.Generic.SortedDictionary2[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryGetValue(System.__Canon, System.__Canon ByRef)
at Microsoft.EntityFrameworkCore.Infrastructure.Annotatable.FindAnnotation(System.String)
at Microsoft.EntityFrameworkCore.Infrastructure.Annotatable.get_Item(System.String)
at Microsoft.EntityFrameworkCore.RelationalModelExtensions.GetDefaultSchema(Microsoft.EntityFrameworkCore.Metadata.IModel)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetDefaultSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions+<>c__DisplayClass6_0.b__4(Microsoft.EntityFrameworkCore.Metadata.ISkipNavigation)
at System.Linq.Enumerable.All[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable1<System.__Canon>, System.Func2<System.__Canon,Boolean>)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetDefaultSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions+<>c__DisplayClass6_0.b__4(Microsoft.EntityFrameworkCore.Metadata.ISkipNavigation)
at System.Linq.Enumerable.All[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable1<System.__Canon>, System.Func2<System.__Canon,Boolean>)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetDefaultSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions+<>c__DisplayClass6_0.b__4(Microsoft.EntityFrameworkCore.Metadata.ISkipNavigation)
at System.Linq.Enumerable.All[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable1<System.__Canon>, System.Func2<System.__Canon,Boolean>)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetDefaultSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions+<>c__DisplayClass6_0.b__4(Microsoft.EntityFrameworkCore.Metadata.ISkipNavigation)
at System.Linq.Enumerable.All[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable1<System.__Canon>, System.Func2<System.__Canon,Boolean>)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetDefaultSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions.GetSchema(Microsoft.EntityFrameworkCore.Metadata.IEntityType)
at Microsoft.EntityFrameworkCore.RelationalEntityTypeExtensions+<>c__DisplayClass6_0.b__4(Microsoft.EntityFrameworkCore.Metadata.ISkipNavigation)
at System.Linq.Enumerable.All[[System.__Canon, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable1<System.__Canon>, System.Func2<System.__Canon,Boolean>)
at
...
etc.

Attached you'll find a repro case. The culprit is this relationship:

protected virtual void MapEmployee(EntityTypeBuilder<Employee> config)
{
	config.ToTable("Employees");
	config.HasKey(t => t.EmployeeId);
	config.Property(t => t.EmployeeId).HasColumnName("EmployeeID").ValueGeneratedOnAdd();
	config.Property(t => t.LastName).HasMaxLength(20).IsRequired();
//...
	config.Property(t => t.RegionId).HasColumnName("RegionID");
	config.OwnsOne(t => t.Address).Property(t => t.Address).HasColumnName("Address").HasMaxLength(60);
	config.OwnsOne(t => t.Address).Property(t => t.City).HasColumnName("City").HasMaxLength(15);
	config.OwnsOne(t => t.Address).Property(t => t.Country).HasColumnName("Country").HasMaxLength(15).IsRequired();
	config.OwnsOne(t => t.Address).OwnsOne(t => t.ZipCodeVtField).Property(t => t.PostalCode).HasColumnName("PostalCode").HasMaxLength(10);
	config.Navigation(t=>t.Address).IsRequired();
	config.HasOne(t => t.Manager).WithMany(t => t.Employees).HasForeignKey(t => t.ReportsTo);
	config.HasOne(t => t.Region1).WithMany(t => t.Employees).HasForeignKey(t => t.RegionId);
	config.HasMany(t => t.RegionCollectionViaEmployee).WithMany(t=>t.EmployeeCollectionViaEmployee).UsingEntity<Employee>(t=>t.HasOne(a=>a.Region1).WithMany(b=>b.Employees), t=>t.HasOne(a=>a.Manager).WithMany(b=>b.Employees));
	config.HasMany(t => t.ShipperCollectionViaOrder).WithMany(t=>t.EmployeeCollectionViaOrder).UsingEntity<Order>(t=>t.HasOne(a=>a.Shipper).WithMany(b=>b.Orders), t=>t.HasOne(a=>a.Employee).WithMany(b=>b.Orders));
	config.HasMany(t => t.TerritoryCollectionViaEmployeeTerritory).WithMany(t=>t.EmployeeCollectionViaEmployeeTerritory).UsingEntity<EmployeeTerritory>(t=>t.HasOne(a=>a.Territory).WithMany(b=>b.EmployeeTerritories), t=>t.HasOne(a=>a.Employee).WithMany(b=>b.EmployeeTerritories));
}

this one:

	config.HasMany(t => t.RegionCollectionViaEmployee).WithMany(t=>t.EmployeeCollectionViaEmployee).UsingEntity<Employee>(t=>t.HasOne(a=>a.Region1).WithMany(b=>b.Employees), t=>t.HasOne(a=>a.Manager).WithMany(b=>b.Employees));

It has a m:n relationship via a relationship with itself. Commenting this m:n relationship mapping fixes it.
It might be I made a mapping mistake, but I don't see how I can map it otherwise.

Repro:
EF5CoreStackOverflowWithMNViaSelf.zip

@ajcvickers
Copy link
Member

@AndriySvyryd Thoughts?

@smitpatel
Copy link
Member

Just want to point out that

config.HasMany(t => t.RegionCollectionViaEmployee).WithMany(t=>t.EmployeeCollectionViaEmployee).UsingEntity<Employee>(t=>t.HasOne(a=>a.Region1).WithMany(b=>b.Employees), t=>t.HasOne(a=>a.Manager).WithMany(b=>b.Employees));

This line is configuring M2M between Employee and Region using Employee as join entity. The 2nd FK in UsingEntity is also self-ref.

@FransBouma
Copy link
Author

It's indeed a self-referencing m:n with itself as the intermediate, as there are two m:1 relationships with the same entity as the 'm' side. It's a bit of an edge case perhaps although self-referencing relationships are sometimes used for m:n relationships...

@AndriySvyryd
Copy link
Member

This isn't something that we support in 5.0, but we should fix the SOE

@FransBouma
Copy link
Author

Ok, I'll make a validation rule to weed out this situation for now :)

@FransBouma
Copy link
Author

@AndriySvyryd

This isn't something that we support in 5.0, but we should fix the SOE

'This' means: a m:n based on a relationship with self or a m:n with self or both?

@ajcvickers
Copy link
Member

Note from triage: we will bring this to Tactics to patch for a better exception than the stack overflow.

@AndriySvyryd AndriySvyryd added the closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. label Nov 24, 2020
@AndriySvyryd AndriySvyryd removed their assignment Nov 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-model-building closed-fixed The issue has been fixed and is/will be included in the release indicated by the issue milestone. customer-reported Servicing-approved type-bug
Projects
None yet
Development

No branches or pull requests

4 participants