Ensure that explicitly set primary key values are unique

c# entity-framework

Question

I am getting following exception on my project:

An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code

Additional information: Saving or accepting changes failed because of more than one entity of type 'MyProject.Data.Poco.MyProjectCountry' have the same primary key value. Ensure that explicitly set primary key values are unique. Ensure that database-generated primary keys are configured correctly in the database and in the Entity Framework model. Use the Entity Designer for Database First/Model First configuration. Use the 'HasDatabaseGeneratedOption" fluent API or 'DatabaseGeneratedAttribute' for Code First configuration.

the error happens at the following line:

using (MyProjectDataContext context = new MyProjectDataContext())
{
    MyProjectItemTag existingItemTag = (from p in context.ItemTags.Include(p => p.MyProjectGenre).Include(p => p.MyProjectCountry)
                                     where p.MyProjectUser.UserId == ItemTag.MyProjectUser.UserId &&
                                           p.MyProjectItem.ItemId == MyProjectItem.ItemId
                                     select p).FirstOrDefault();


    // new tag
    if (existingItemTag == null)
    {
        existingItemTag = ItemTag;
        existingItemTag.MyProjectItem.ItemId = MyProjectItem.ItemId;
    }
    // existing tag
    else
    {
        existingItemTag.MyProjectItem = new MyProjectItem { ItemId = MyProjectItem.ItemId };
        existingItemTag.MyProjectUser = new MyProjectUser { UserId = ItemTag.MyProjectUser.UserId };
    }
    // updates
    existingItemTag.MyProjectCountry = MyProjectCountry;
    if (MyProjectCountry != null)
    existingItemTag.MyProjectCountry = new MyProjectCountry()
    {
        MyProjectCountryId = MyProjectCountry.MyProjectCountryId
    };
    existingItemTag.MyProjectGenre = MyProjectGenre;
    context.Entry(existingItemTag.MyProjectItem).State = EntityState.Unchanged;
    context.Entry(existingItemTag.MyProjectUser).State = EntityState.Unchanged;
    context.Entry(existingItemTag.MyProjectCountry).State = EntityState.Unchanged;
    context.Entry(existingItemTag.MyProjectGenre).State = EntityState.Unchanged;
    if (existingItemTag.MyProjectCountry != null)
    {
        context.Entry(existingItemTag.MyProjectCountry).State = EntityState.Unchanged;
    }
    // db
    context.ItemTags.AddOrUpdate(existingItemTag);
    context.SaveChanges();
    return existingItemTag.ItemTagId;
}

 context.Entry(existingItemTag.MyProjectCountry).State = EntityState.Unchanged;

My Class:

public class MyProjectItemTag
{
    public int ItemTagId { get; set; }
    public MyProjectUser MyProjectUser { get; set; }
    public MyProjectItem MyProjectItem { get; set; }
    public MyProjectCountry MyProjectCountry { get; set; }
    public MyProjectGenre MyProjectGenre { get; set; }
    public MyProjectMood MyProjectMood { get; set; }

    public MyProjectItemTag()
    {
    }

    public MyProjectItemTag(string userId, string providerContentId)
    {
        MyProjectUser = new MyProjectUser
        {
            UserId = userId
        };

        MyProjectItem = new MyProjectItem
        {
            ProviderContentId = providerContentId
        };
    }
}

My Config:

public class MyProjectItemTagConfiguration : EntityTypeConfiguration<MyProjectItemTag>
{
    public MyProjectItemTagConfiguration()
    {
        ToTable("MyProjectItemTags");
        HasKey(p => p.ItemTagId);
        HasRequired(p => p.MyProjectUser);
        HasRequired(p => p.MyProjectItem);
        HasOptional(p => p.MyProjectCountry);
    }
}

What I am missing here?

1
0
1/12/2020 12:46:19 AM

Accepted Answer

This is all you really need to look for:

Additional information: Saving or accepting changes failed because more than one entity of type 'MyProject.Data.Poco.MyProjectCountry' have the same primary key value.

The following code may not necessarily populate the MyProjectCountry.

MyProjectItemTag existingItemTag = 
  (from p in context.ItemTags
    .Include(p => p.MyProjectGenre)
    .Include(p => p.MyProjectCountry)
   where p.MyProjectUser.UserId == ItemTag.MyProjectUser.UserId 
     && p.MyProjectItem.ItemId == MyProjectItem.ItemId
   select p).FirstOrDefault();

So you set it to some variable you haven't give us any context too...

existingItemTag.MyProjectCountry = MyProjectCountry;

I'd assume it is not null, so you change it's ID which is a Giant Code Smell...

(Why assign it? after all it's already assigned..)

if (MyProjectCountry != null)
  existingItemTag.MyProjectCountry = new MyProjectCountry()
  {
    MyProjectCountryId = MyProjectCountry.MyProjectCountryId
  };

Then you tell EF it hasn't changed?? Another Code Smell.

context.Entry(existingItemTag.MyProjectCountry).State = EntityState.Unchanged;

So what this tells me is that the Context has already downloaded this entity into its Object Cache, but the one you are assigning is not the one in the cache so when I tries to added to the cache, there is a duplicate.

1
7/13/2015 3:10:55 AM

Popular Answer

Try to use context.Model.AddORUpdate(model) Method, you need to add using System.Data.Entity.Migrations as well for this method.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow