Ef Core - weird behavior of AddRange

senglory 1 Reputation point
2021-03-12T20:27:35.6+00:00

Here's my code:

[Table("prom_term", Schema = "demo")]
    public class PromTerm
    {
        [Key]
        [Column("promotion_terminal_id")]
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id { get; set; }
        [Column("promotion_id")]
        public int Promotionld { get; set; }
        [ForeignKey("Promotionld")]
        public DbPromotion Promotion { get; set; }
        [Column("pos_terminal_id")]
        public string POSTerminalld { get; set; }
        [Column("retailer_name")]
        public string RetailerName { get; set; }
        [Column("promotion_report_period_id")]
        public int ReportPeriodld { get; set; }
        [ForeignKey("ReportPeriodId")]
        public PromReportPeriod RepoortPeriod { get; set; }
    }

    public class FamilyTeamSvcDbContext : DbContext
    {

        ...
        public DbSet<PromTerm> PromotionTerminals { get; set; }
    }

            using var ctx = new FamilyTeamSvcDbContext(options);
            var promoTerminals = new List<PromTerm>{
                    new PromTerm
                    {
                        POSTerminalId="777777", 
                        RetailerName="8888"
                    },
                    new PromTerm
                    {
                        POSTerminalId="333",
                        RetailerName="AAA"
                      },
                      new PromTerm
                    {
                        POSTerminalId="qqq",
                        RetailerName="AAA"
                    },
                    new PromTerm
                    {
                        POSTerminalId="qqq",
                        RetailerName="BBB"
                    }
                }
                ;
            promoTerminals.ForEach(x => {
                x.Promotionld = 1;
                x.ReportPeriodld = 2;
                //ctx.PromotionTerminals.Append(x);
                }
            );

            ctx.PromotionTerminals.AddRange(promoTerminals);

Right at the last line I get this exception:

System.InvalidOperationException : The instance of entity type 'PromTerm' cannot be tracked because another instance with the same key value for {'PromotionId', > 'POSTerminalId'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using > 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.
Stack Trace:
IdentityMap1.ThrowIdentityConflict(InternalEntityEntry entry) IdentityMap1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
IdentityMap1.Add(TKey key, InternalEntityEntry entry) NullableKeyIdentityMap1.Add(InternalEntityEntry entry)
StateManager.StartTracking(InternalEntityEntry entry)
InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges, Boolean modifyProperties)
InternalEntityEntry.SetEntityState(EntityState entityState, Boolean acceptChanges, Boolean modifyProperties, Nullable1 forceStateWhenUnknownKey) EntityGraphAttacher.PaintAction(EntityEntryGraphNode1 node)
EntityEntryGraphIterator.TraverseGraph[TState](EntityEntryGraphNode1 node, Func2 handleNode)
EntityGraphAttacher.AttachGraph(InternalEntityEntry rootEntry, EntityState targetState, EntityState storeGeneratedWithKeySetTargetState, Boolean > forceStateWhenUnknownKey)
InternalDbSet`1.SetEntityState(InternalEntityEntry entry, EntityState entityState)

I> nternalDbSet1.SetEntityStates(IEnumerable1 entities, EntityState entityState)

InternalDbSet1.AddRange(IEnumerable1 entities)

Why does it treat 'PromotionId' +'POSTerminalId' as a key still a bit beyond me. My schema does not have these fields as a multi-column key. But there's one more weird behavior — if I uncomment Append() and comment AddRange(), then adding starts working. What am I doing wrong?

Entity Framework Core
Entity Framework Core
A lightweight, extensible, open-source, and cross-platform version of the Entity Framework data access technology.
694 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Daniel Zhang-MSFT 9,611 Reputation points
    2021-03-15T06:11:31.51+00:00

    Hi senglory-6433,
    The error indicates that your DB Context is being shared by multiple requests, meaning that the entity you're editing has been tracked already.
    This is most likely because your repository service is Singleton instead of Scoped, so when you pull the database context and put it back into the same instance of the database context, the database context will be reused.
    And when you call DbContext.AddRange method, it indicates that the entity has been tracked and is in the added state.
    So I suggest you can disable tracking via AsNoTracking or changing EntityState to Detached.
    Best Regards,
    Daniel Zhang


    If the response is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.