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

Migrations do not work when an owned type property is called Item #25501

Closed
glards opened this issue Aug 12, 2021 · 4 comments · Fixed by #25960
Closed

Migrations do not work when an owned type property is called Item #25501

glards opened this issue Aug 12, 2021 · 4 comments · Fixed by #25960
Labels
area-migrations 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 type-bug
Milestone

Comments

@glards
Copy link

glards commented Aug 12, 2021

After migrating a project running from .NET 5 / EFCore 5 to the preview 7 of .NET 6 / EFCore 6, I am unable to run the project because the migration fails. I found out that the cause was an owned type with a property name of 'Item'.

When running the command 'dotnet ef database update', the following error is displayed (full output is below) :

The collection navigation 'Item' cannot be added to the entity type 'Order (Dictionary<string, object>)' because its CLR type 'object' does not implement 'IEnumerable<Dictionary<string, object>>'. Collection navigations must implement IEnumerable<> of the related entity.
Full command output
Build started...
Build succeeded.
Applying migration '20210812142100_InitialMigration'.
System.InvalidOperationException: The collection navigation 'Item' cannot be added to the entity type 'Order (Dictionary<string, object>)' because its CLR type 'object' does not implement 'IEnumerable<Dictionary<string, object>>'. Collection navigations must implement IEnumerable<> of the related entity.
   at Microsoft.EntityFrameworkCore.Metadata.Internal.Navigation.IsCompatible(String navigationName, MemberInfo navigationProperty, EntityType sourceType, EntityType targetType, Nullable`1 shouldBeCollection, Boolean shouldThrow) in Microsoft.EntityFrameworkCore.dll:token 0x6001351+0xb1
   at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.AddNavigation(MemberIdentity navigationMember, ForeignKey foreignKey, Boolean pointsToPrincipal) in Microsoft.EntityFrameworkCore.dll:token 0x6000e69+0x10a
   at Microsoft.EntityFrameworkCore.Metadata.Internal.EntityType.AddNavigation(String name, ForeignKey foreignKey, Boolean pointsToPrincipal) in Microsoft.EntityFrameworkCore.dll:token 0x6000e67+0x1f
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKey.Navigation(Nullable`1 propertyIdentity, ConfigurationSource configurationSource, Boolean pointsToPrincipal) in Microsoft.EntityFrameworkCore.dll:token 0x6000fca+0x175
   at Microsoft.EntityFrameworkCore.Metadata.Internal.ForeignKey.SetPrincipalToDependent(String name, ConfigurationSource configurationSource) in Microsoft.EntityFrameworkCore.dll:token 0x6000fc6+0xc
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalForeignKeyBuilder.HasNavigations(Nullable`1 navigationToPrincipal, Nullable`1 navigationToDependent, EntityType principalEntityType, EntityType dependentEntityType, ConfigurationSource configurationSource) in Microsoft.EntityFrameworkCore.dll:token 0x6001130+0x75a
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalForeignKeyBuilder.HasNavigations(Nullable`1 navigationToPrincipal, Nullable`1 navigationToDependent, ConfigurationSource configurationSource) in Microsoft.EntityFrameworkCore.dll:token 0x600112d+0x0
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalForeignKeyBuilder.HasNavigation(String name, Boolean pointsToPrincipal, ConfigurationSource configurationSource) in Microsoft.EntityFrameworkCore.dll:token 0x6001129+0x18
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.HasRelationship(EntityType targetEntityType, Nullable`1 navigationToTarget, Nullable`1 inverseNavigation, Nullable`1 setTargetAsPrincipal, ConfigurationSource configurationSource, Nullable`1 required) in Microsoft.EntityFrameworkCore.dll:token 0x60010a0+0x8b7
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.HasOwnership(TypeIdentity& targetEntityType, MemberIdentity& navigation, Nullable`1 inverse, ConfigurationSource configurationSource) in Microsoft.EntityFrameworkCore.dll:token 0x60010ab+0x1f6
   at Microsoft.EntityFrameworkCore.Metadata.Internal.InternalEntityTypeBuilder.HasOwnership(TypeIdentity& typeIdentity, MemberIdentity navigation, ConfigurationSource configurationSource) in Microsoft.EntityFrameworkCore.dll:token 0x60010a8+0x0
   at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsOneBuilder(TypeIdentity& ownedType, String navigationName) in Microsoft.EntityFrameworkCore.dll:token 0x6001770+0x1e
   at Microsoft.EntityFrameworkCore.Metadata.Builders.EntityTypeBuilder.OwnsOne(String ownedTypeName, String navigationName, Action`1 buildAction) in Microsoft.EntityFrameworkCore.dll:token 0x600176d+0x2c
   at EFTest.Migrations.InitialMigration.<>c.<BuildTargetModel>b__2_1(EntityTypeBuilder b) in D:\Src\test\EFTest\Migrations\20210812142100_InitialMigration.Designer.cs:line 36
   at Microsoft.EntityFrameworkCore.ModelBuilder.Entity(String name, Action`1 buildAction) in Microsoft.EntityFrameworkCore.dll:token 0x600027d+0xc
   at EFTest.Migrations.InitialMigration.BuildTargetModel(ModelBuilder modelBuilder) in D:\Src\test\EFTest\Migrations\20210812142100_InitialMigration.Designer.cs:line 34
   at Microsoft.EntityFrameworkCore.Migrations.Migration.<get_TargetModel>g__Create|5_0() in Microsoft.EntityFrameworkCore.Relational.dll:token 0x6000cc3+0x6
   at Microsoft.EntityFrameworkCore.Migrations.Migration.get_TargetModel() in Microsoft.EntityFrameworkCore.Relational.dll:token 0x6000cb9+0xa
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.GenerateUpSql(Migration migration, MigrationsSqlGenerationOptions options) in Microsoft.EntityFrameworkCore.Relational.dll:token 0x6000f4f+0x33
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.<>c__DisplayClass16_2.<GetMigrationCommandLists>b__2() in Microsoft.EntityFrameworkCore.Relational.dll:token 0x6001d01+0x26
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration) in Microsoft.EntityFrameworkCore.Relational.dll:token 0x6000f4a+0x92
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType) in Microsoft.EntityFrameworkCore.Design.dll:token 0x6000478+0x2e
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType) in Microsoft.EntityFrameworkCore.Design.dll:token 0x60003e7+0x0
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0() in Microsoft.EntityFrameworkCore.Design.dll:token 0x60006e3+0x0
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action) in Microsoft.EntityFrameworkCore.Design.dll:token 0x600066a+0xc
The collection navigation 'Item' cannot be added to the entity type 'Order (Dictionary<string, object>)' because its CLR type 'object' does not implement 'IEnumerable<Dictionary<string, object>>'. Collection navigations must implement IEnumerable<> of the related entity.

To reproduce this error use the program below and run the following commands :

dotnet ef migrations add InitialMigration
dotnet ef database update
Program that reproduce the error
using System;
using Microsoft.EntityFrameworkCore;

using var db = new TestContext();

db.Add(new Order()
{
    ShippingAddress = new StreetAddress("AAA", "BBB"),
    Item = new MyItem(1, 2)
});

db.SaveChanges();

public record MyItem(int A, int B);

public record StreetAddress(string Street, string City);

public class Order
{
    public int Id { get; set; }
    public StreetAddress ShippingAddress { get; set; }
    public MyItem Item { get; set; }
}

public class TestContext : DbContext
{
    public DbSet<Order> Orders { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFOwnedEntity;Trusted_Connection=True");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>().OwnsOne(x => x.ShippingAddress);
        modelBuilder.Entity<Order>().OwnsOne(x => x.Item);
    }
}

Having only the ShippingAddress property works correctly as well as renaming the property Item to anything else. It only breaks with the name 'Item'.

EF Core version: 6.0.0-preview.7.21378.4
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0.100-preview.7.21379.14
Operating system: Windows 10
IDE: Visual Studio 2022 Preview 3

@smitpatel
Copy link
Contributor

Duplicate of #25485

@smitpatel smitpatel marked this as a duplicate of #25485 Aug 12, 2021
@glards
Copy link
Author

glards commented Sep 3, 2021

I tried the daily build containing #25809 and the issue is still there.

I have looked a bit at what the code from the migration does and I could reduce the issue to this unit test :

        [ConditionalFact]
        public void Can_own_property_with_clrtypes_name()
        {
            var modelBuilder = CreateModelBuilder();
            var orderEntityBuilder = modelBuilder.Entity("Order", ConfigurationSource.Explicit);
            orderEntityBuilder.HasOwnership(new TypeIdentity("MyType"), new MemberIdentity("Other"), ConfigurationSource.Explicit);
            orderEntityBuilder.HasOwnership(new TypeIdentity("MyType"), new MemberIdentity("Item"), ConfigurationSource.Explicit);
        }

The HasOwnership call works correctly with the "Other" MemberIdentity but fails with "Item". It throws the exception seen in the initial report.

@smitpatel smitpatel reopened this Sep 3, 2021
@smitpatel
Copy link
Contributor

The fix was made to make sure that EF Core never calls HasOwnership when the member name is Item. If you are calling it yourself then yes, it will run into error. If you can provide a repro code which demonstrate that trying to build model via ModelBuilder is causing this issue even after the fix, then we can investigate.

@glards
Copy link
Author

glards commented Sep 3, 2021

The repro code is the one in the issue above.

After running the command 'dotnet ef migrations add InitialMigration', the migration contains the following code:

modelBuilder.Entity("Order", b =>
{
	b.OwnsOne("MyItem", "Count", b1 =>
	{
		// ...
	}
}

This part of the code is calling the model builder in the same way I did in the previous comment. You can also see in the stacktrace given by the command 'dotnet ef database update' that it calls HasOwnership.

@ajcvickers ajcvickers added this to the 6.0.0 milestone Sep 4, 2021
@AndriySvyryd AndriySvyryd removed their assignment Sep 9, 2021
@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 Sep 9, 2021
AndriySvyryd added a commit that referenced this issue Sep 10, 2021
…erties.

Make GetIdentifyingMemberInfo() return null for indexer properties since it doesn't uniquely identifies them
Replaced some usages of GetIdentifyingMemberInfo() with more appropriate code.

Fixes #25501
Fixes #25459
AndriySvyryd added a commit that referenced this issue Sep 10, 2021
…erties.

Make GetIdentifyingMemberInfo() return null for indexer properties since it doesn't uniquely identifies them
Replaced some usages of GetIdentifyingMemberInfo() with more appropriate code.

Fixes #25501
Fixes #25459
AndriySvyryd added a commit that referenced this issue Sep 10, 2021
…erties.

Make GetIdentifyingMemberInfo() return null for indexer properties since it doesn't uniquely identify them
Replaced some usages of GetIdentifyingMemberInfo() with more appropriate code.

Fixes #25501
Fixes #25459
@ajcvickers ajcvickers modified the milestones: 6.0.0, 6.0.0-rc2 Sep 10, 2021
@ajcvickers ajcvickers modified the milestones: 6.0.0-rc2, 6.0.0 Nov 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-migrations 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 type-bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants