Neil Hosey
Neil Hosey

Reputation: 465

Violation of PRIMARY KEY constraint 'PK_dbo.AmazonProducts'. Cannot insert duplicate key in object

I have a problem trying to save an entity which is a foreign key to a parent object..

i have an amazonProduct entity. And an AmazonCompetitivePrice entity which is a virtual list on the amazonProduct like so :

public class AmazonProduct
{
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public virtual int ASIN

        public virtual IList<AmazonProductCompetitivePrice> amazonProductCompetitivePrices = new List<AmazonProductCompetitivePrice>();
}

So i have a AmazonProduct which i retrieve from the database, and then add a new AmazonProductCompetitivePrice to the amazonProduct.

But when i try save this, I get the following error:

Violation of PRIMARY KEY constraint 'PK_dbo.AmazonProducts'. Cannot insert duplicate key in object 'dbo.AmazonProducts'.\r\nThe statement has been terminated

It looks like its not realising that my AmazonProduct is already in the database, and its trying to save a new one but the primary key already exists!

I used the fluent API to map the foreign key like so:

        modelBuilder.Entity<AmazonProduct>()
                    .HasMany(pl => pl.AmazonProductCompetitivePrices)
                    .WithOptional(p => p.AmazonProduct)
                    .Map(c => c.MapKey("ASIN"));

Anyone know whats wrong with this?

Thanks in advance!

EDIT: object retrieval:

 using (var uow = new UnitOfWorkInventory())
            {
                using (var amazRepo = new AmazonProductRepository(uow))
                {
                    return amazRepo.FindByAsin(ASIN);
                }
            }
 public AmazonProduct FindByAsin(string asin)
        {
            return context.AmazonProducts.Include(x => x.AmazonLowestOfferListings).Include(x => x.AmazonMyPrices).Include(x => x.AmazonProductCompetitivePrices).SingleOrDefault(x => x.ASIN == asin);
        }

That gets me the AmazonProduct.. then the save:

using (var uow = new UnitOfWorkInventory())
{
     using (var amazonRepo = new AmazonProductCompetitivePriceRepository(uow))
     {
          amazonProductCompetitivePrice.AmazonProduct = amazonProduct;
          amazonRepo.InsertOrUpdate(amazonProductCompetitivePrice);
     }
          uow.Commit();
}

  public void InsertOrUpdate(AmazonProductCompetitivePrice amazonProductCompetitivePrice)
    {
        if (amazonProductCompetitivePrice.Id == default(int))
        {
            // New entity
            context.AmazonProductCompetitivePrices.Add(amazonProductCompetitivePrice);
        }
        else
        {
            // Existing entity
            context.Entry(amazonProductCompetitivePrice).State = EntityState.Modified;
        }
    }

Thats everything.. and thanks for the help!!

Upvotes: 3

Views: 8084

Answers (2)

Elnaz
Elnaz

Reputation: 2900

I had this problem first of all I Deleted

[DatabaseGenerated(DatabaseGeneratedOption.None)]

annotation from my entity class. then, I dropped the table from my sql server manually and again used update-database -Verbose in NuGet package manager Console. now, it works!

Upvotes: 0

Dennis
Dennis

Reputation: 37780

This line:

amazonProductCompetitivePrice.AmazonProduct = amazonProduct;

adds amazonProduct instance to context implicitly. Because that instance was retrieved with different instance of context, current instance thinks, that it is new AmazonProduct. You should attach it instead, something like this:

if (amazonProductCompetitivePrice.AmazonProduct != null && amazonProductCompetitivePrice.AmazonProduct.Id != 0)
{
  context.Entry(amazonProductCompetitivePrice.AmazonProduct).State = EntityState.Unchanged;
}

Another way: you can set foreign key property only for amazonProductCompetitivePrice instead of navigation property.

Upvotes: 5

Related Questions