更新错误:导航属性违反PRIMARY KEY约束

时间:2016-05-26 21:57:47

标签: c# entity-framework

  

违反PRIMARY KEY约束'PK_dbo.SongCategories'。无法在对象'dbo.SongCategories'中插入重复键。重复键值为(2,3)。   声明已经终止。

我试图让用户编辑歌曲导航属性。

public class Song 
{
    //AudioName, Artist etc
    ...
    public virtual ICollection<Category> Categories { get; set; }
}

public class Category
{
    ...
    public virtual ICollection<Song> Songs { get; set; }
}

EF使用列Song_IdCategory_Id创建一个SongCategories表。

控制器:

[HttpPost]
public ActionResult RequestEdit(EditSongDto editSongDto)
 {
      var categories = _categoryService.GetCategories().Where(x => editSongDto.SelectedCategoryIds.Any(z => z == x.Id));
      _songService.Edit(_songService.GetSong(editSongDto.Song.Id), editSongDto.AudioName, editSongDto.ArtistName, categories);   
}

服务:

public void Edit(Song song, string audioName, string artistName, IEnumerable<Category> categories)
{
    song.AudioName = audioName;
    song.ArtistName = artistName;

    song.Categories = categories.ToList();

    _repository.Edit(song);
}

存储库:

public virtual void Edit(T entity)
{
   _context.Entry(entity).State = EntityState.Modified;
   Save();
}

当再次传入同一个传递时会发生这种情况。如何正确更新导航属性?我看过其他主题,但仍然不知道答案。

1 个答案:

答案 0 :(得分:1)

EF与多对多关系很棘手。我相信在使用song.Categories覆盖延迟加载categories.ToList()之前,它不会对其进行更改,因此它不会意识到现有的song-Category关系

通过调用song.Categories.Clear(),您可以强制延迟加载并明确声明要删除该特定歌曲的现有song-Category关系。接下来,您可以通过覆盖Categories集合和EF&#34;修复&#34;来分配新关系。生成正确INSERT/DELETE语句的所有内容

public void Edit(Song song, string audioName, string artistName, IEnumerable<Category> categories)
{
    song.AudioName = audioName;
    song.ArtistName = artistName;

    song.Categories.Clear();
    song.Categories = categories.ToList();

    _repository.Edit(song);
}

也许更好的方法是迭代song.Categories删除新类别列表中未包含的内容,然后从类别列表中添加song.Categories中没有的内容但我还没有自己测试了