确保显式设置的主键值是唯一的

时间:2015-07-12 21:48:48

标签: c# entity-framework

我的项目有以下异常;

  

类型' System.InvalidOperationException'的例外情况发生在   EntityFramework.dll但未在用户代码中处理

     

其他信息:保存或接受更改失败,原因是:   不止一个类型的实体' MyProject.Data.Poco.MyProjectCountry'有   相同的主键值。确保显式设置主键值   很独特。确保已配置数据库生成的主键   正确地在数据库和实体框架模型中。使用   数据库优先/模型优先配置的实体设计器。使用   ' HasDatabaseGeneratedOption"流利的API或   ' DatabaseGeneratedAttribute'用于Code First配置。

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

我在这里缺少什么?

2 个答案:

答案 0 :(得分:1)

这是您真正需要寻找的所有内容:

  

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

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

我认为它不是空的,所以你改变了它的巨人身份Code Smell ...

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

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

然后你告诉EF它没有改变?另一个代码嗅觉。

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

所以这告诉我的是Context已经将这个实体下载到它的对象缓存中,但是你分配的那个不是缓存中的那个,所以当我尝试添加到缓存时,有一个重复。

答案 1 :(得分:0)

尝试使用context.Model.AddORUpdate(model)方法,此方法还需要使用System.Data.Entity.Migrations添加。