EF代码中这种多对多关系有什么问题

时间:2014-09-25 03:29:35

标签: .net entity-framework entity-framework-6

我正在使用Code First,EF 6.0并尝试在请求和标记表之间实现多对多关系。

关系设置正确为:

HasMany(b => b.Tags).WithMany().Map(mc => mc.MapLeftKey("RequestID").MapRightKey("TagID").ToTable("requesttags"));

一切都很好看。但是,当涉及到Request的插入标记时,我以三种方式插入:

>   if (request.Tags == null)
>             {
>                 entity.Tags = new List<Tag>();
>             }
>              // 1 way get the tag and then insert.
>             var tag = _tagService.Get(1);
               // 2 and 3 way hard code id with the name. 
>             var tags = new List<Tag> {tag, new Tag {Name = ".Net", ID = 2}, new Tag {Name = "C#"}};
> 
>             request.Tags.AddRange(tags);

执行插入操作。但是,当我看到最终结果时:第一个标签已正确引用。但是对于两个标签,即使ID和名称匹配,它仍然在Tag表中创建一个新记录并进行引用。

我的想法是因为第一个标记对象是从数据库获取并附加的。但为什么我必须附上?

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

  

但为什么我必须附上?

因为它们是断开连接的对象,将被视为新对象。当您将tags添加到request.Tags时,它们都会被标记为已添加,因为EF并不知道它们都是现有实体。

您只需循环Tags即可查看每个代码的状态。

request.Tags.AddRange(tags);
foreach(var tag in tags)
{
    Console.WriteLine(dbContext.Entry(tag).State);
}

输出应该是:

Unchanged
Added
Added
  

我该如何解决这个问题?

只需Attach或将Unchanged标记为已断开连接的对象。

dbContext.Entry(tags[1]).State = EntityState.Unchanged;
// equals to dbContext.Set<Tag>().Attach(tags[1]);
dbContext.Entry(tags[2]).State = EntityState.Unchanged;
// equals to dbContext.Set<Tag>().Attach(tags[2]);

确保两个实体都是现有实体,否则在调用DbUpdateException时会抛出SaveChanges