2015-07-12 109 views
0

我在我的项目中遇到以下异常;确保显式设置的主键值是唯一的

类型的异常“System.InvalidOperationException”发生在 EntityFramework.dll但在用户代码中没有处理

其他信息:保存或接受更改失败类型的“,因为 多于一个实体MyProject的.Data.Poco.MyProjectCountry'具有相同的主键值 。确保明确设置的主键值 是唯一的。确保数据库生成的主键在数据库和实体框架模型中正确配置为 。使用 实体设计器进行数据库优先/模型优先配置。使用 “HasDatabaseGeneratedOption”一口流利的API或 'DatabaseGeneratedAttribute' 的代码首先配置

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; 

我的班级;

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 
      }; 

} }

我的配置;

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); 
     } 
    } 

我在这里失踪了什么?

+0

当'existingItemTag'是新的时候,你重新插入一个正在退出的'Country'。 –

+0

我缺少的是== nulll的情况下,你做... existingItemTag = ItemTag;什么是ItemTag?这是一个财产吗?它是什么?我认为这个问题的答案是回答你的问题的关键。 – Mick

回答

2

这是你真正需要寻找:

其他信息:保存或接受更改失败,因为类型的多个实体“MyProject.Data.Poco.MyProjectCountry”具有相同的主键值。

以下代码可能不一定会填充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(); 

所以将它设置为某个变量你还没有给我们太多的任何上下文...

existingItemTag.MyProjectCountry = MyProjectCountry; 

我认为它不为空,所以你改变它的ID是一个巨人Code Smell ...

(为什么分配呢?毕竟它已经分配..)

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

然后你牛逼它的EF没有改变?另一个代码嗅觉。

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

所以这告诉我的是,语境已经下载这个实体到其对象缓存,但你分配一个是不是一个在缓存中,所以当我试图添加到缓存中,有是重复的。

+0

这是真的,上下文具有相同对象的重复缓存,因此失败。 –