asp.net mvc更新导航集合

时间:2016-05-27 16:20:36

标签: c# asp.net-mvc entity-framework

如何在保持实体框架跟踪的同时更新导航集合属性?

域:

public class BuyLink
{
    public int Id { get; set; }

    string _buyLinkUrl;
    public string BuyLinkUrl
    {
        get
        { return _buyLinkUrl; }
        set
        {
            if (!string.IsNullOrWhiteSpace(value))
                _buyLinkUrl = value;
        }
    }
}

DTO:

public class BuyLinkDto
{
    public int Id { get; set; }

    public string BuyLinkUrl { get; set; }
}

控制器:

例如,_songService.GetSong(editSongDto.Song.Id).BuyLinks确实通过跟踪获取当前的buyLinks,但是,如何使用用户提供的editSongDto.BuyLinks编辑更新此集合,而不会丢失此跟踪更改?

[HttpPost]
public ActionResult RequestEdit(EditSongDto editSongDto)
{
    //Doesn't work well because entity Framework doesn't track with this assignment so it adds to the database instead of updating.
    var buyLinks = _songService.GetSong(editSongDto.Song.Id).BuyLinks = editSongDto.BuyLinkDtos.Select(x => new BuyLink { BuyLinkUrl = x.BuyLinkUrl }).ToList();

    _songService.Edit(_songService.GetSong(editSongDto.Song.Id), editSongDto.AudioName, editSongDto.ArtistName, buyLinks);

      return View("Index");
}

服务:

public void Edit(Song song, string audioName, string artistName, IEnumerable<BuyLink> buyLinks)
{
    song.AudioName = audioName;
    song.ArtistName = artistName;
    song.BuyLinks = buyLinks?.ToList();

    _repository.Edit(song);
}

回购:

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

1 个答案:

答案 0 :(得分:1)

更新实体时,应始终使用数据库中的新实例,而不是创建新实例并尝试使用该实例覆盖现有实例。换句话说:

var song = _songService.GetSong(editSongDto.Song.Id);
var buyLinks = song.BuyLinks.ToList();

...

foreach (var buyLinkDto in editSongDto.BuyLinkDtos)
{
    var buyLink = buyLinks.SingleOrDefault(m => m.Id != 0 && m.Id == buyLinkDto.Id);

    // New BuyLink
    if (buyLink == null)
    {
        buyLink = new BuyLink { BuyLinkUrl = buyLinkDto.BuyLinkUrl };
        song.BuyLinks.Add(buyLink);
    }
    // Existing BuyLink
    else
    {
        buyLink.BuyLinkUrl = buyLinkDto.BuyLinkUrl;
    }
}

现在,实体框架确切地知道发生了什么,并将适当地插入/更新。