简体   繁体   中英

How can I add multiple navigation properties with the same Foreign Key in EF.Core 5?

I am trying to add a collection of new objects in EF.Core 5. These objects contain a one-to-many relationship expressed in a navigation property as well as a property that contains the FK object.

Whenever I try and.AddRange(entities); I get "The instance of entity type '{object}' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked."

How can I get ef.core to understand that the navigation property is identical and to only insert once?

Also, I'm not yet worried about what is actually in the database, this fails when I call.AddRange(entities); for the first time after constructing the context.

I did break this into a foreach loop and can see that it's the 2nd instance of the Holder object when the exception is thrown, which tells me that EF.Core doesn't know how to handle a 2nd instance of the "same" object.

json

[
   {
      "Id":637535121932347380,
      "HolderId":100,
      "Holder":{
         "Id":100,
         "Name":"Unit Test 0",
         "Nickname":"Nickname 0"
      }
   },
   {
      "Id":637535121932363243,
      "HolderId":100,
      "Holder":{
         "Id":100,
         "Name":"Unit Test 0",
         "Nickname":"Nickname 0"
      }
   },
   {
      "Id":637535121932363330,
      "HolderId":100,
      "Holder":{
         "Id":100,
         "Name":"Unit Test 0",
         "Nickname":"Nickname 0"
      }
   }
]

Business logic

_context.Properties.AddRange(entities);
await _context.SaveChangesAsync(cancellationToken);

EF.Core Fluent Mapping

 internal sealed class HolderMap : IEntityTypeConfiguration<Holder>
    {
        public void Configure(EntityTypeBuilder<Holder> builder)
        {
            builder.HasKey(p => p.Id);
            builder.Property(p => p.Id).ValueGeneratedNever().IsRequired();
            builder.Property(p => p.Name).IsRequired().HasMaxLength(80);
            builder.Property(p => p.Nickname).HasMaxLength(96);
            
            builder.HasMany(p => p.Properties).WithOne(p => p.Holder).HasForeignKey(h => h.HolderId);
        }
    }

 internal sealed class PropertyMap : IEntityTypeConfiguration<Property>
    {
        public void Configure(EntityTypeBuilder<Property> builder)
        {
            builder.HasKey(p => p.Id);
            builder.Property(p => p.Id).ValueGeneratedNever().IsRequired();
           
            //relationships
            builder.HasOne(p => p.Holder).WithMany(h => h.Properties).HasForeignKey(k => k.HolderId);         

        }
    }

Right now I am getting the error message "When attaching existing entities, ensure that only one entity instance with a given key value is attached."

I wonder how you create entities from in the first place? If you have something like

MyEntity myEntity = new () {
    Id = 637535121932347380,
    Holder = new() {
        Id = 10,
        Name = "Unit Test 0"
    }
}

then you don't need to explicitly assign HolderId - Entity Framework will figure it by itself. Because you are assigning, it probably thinks that there is another Holder object with the same key

UPDATE : if the first assignment works fine, and the second throws exception - even more curious how do you do the assignment? I assume you ICollection<MyEntity> on the one side of the relationship. What if you assign MyEntity es to the collection instead?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM