实体框架模型中的集合未更新

时间:2019-02-09 02:23:57

标签: c# database entity-framework entity-framework-6

我有几个简单的模型。一个PlaylistEntry模型和一个包含PlaylistEntry模型集合的Playlist模型。

播放列表:

    public class Playlist
    {
        private ICollection<PlaylistEntry> playlistEntries;

        public int PlaylistId { get; set; }

        public string Name { get; set; }

        public virtual ICollection<PlaylistEntry> PlaylistEntries
        {
            get => this.playlistEntries ?? (this.playlistEntries = new HashSet<PlaylistEntry>());
            set => this.playlistEntries = value;
        }
    }

PlaylistEntry

    public class PlaylistEntry
    {
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int PlaylistEntryId { get; set; }

        public string FilePath { get; set; }

        [ForeignKey("Playlist")]
        public int PlaylistId { get; set; }

        [Required]
        public Playlist Playlist { get; set; }
    }

当我以分离状态将播放列表条目添加到播放列表时,我希望在附加并保存更改时,对播放列表条目列表的更改也将被保存。他们不保存,列表为空。

这是我的代码:

    var playlist = new Playlist { Name = "My first playlist" };
    using (var context = new MusicPlayerContext(stringBuilder))
    {
        context.Playlists.Add(playlist);
        context.SaveChanges();
    }

    playlist.PlaylistEntries.Add(new PlaylistEntry { FilePath = "lkdfj", PlaylistId = playlist.PlaylistId });

    using (var context = new MusicPlayerContext(stringBuilder))
    {
        context.Playlists.Attach(playlist);
        context.Entry(playlist).State = EntityState.Modified;
        context.SaveChanges();
    }

    using (var context = new MusicPlayerContext(stringBuilder))
    {
        context.Playlists.Include(x => x.PlaylistEntries).ToList();
    }

最后一个ToList调用返回我创建的播放列表,但其上的PlaylistEntries集合为空。

任何人都可以发现我在做什么错或建议其他解决方案吗?我已经花了大约7个小时,无法解决我的一生。

3 个答案:

答案 0 :(得分:3)

您缺少的功能是上下文缓存的工作方式。当您将实体(手动或通过从数据库请求实体)附加到上下文时,实体框架会监视以进行更改并跟踪这些更改。

您已将一个对象添加到实体的属性中,然后将其添加到上下文中。实体框架现在正在监视它是否需要更改以进行任何其他工作。以此方式添加的所有 对象都标记为未更改。将父项标记为 changed 不会将导航属性标记为 changed

您可以将实体添加到上下文中的属性中:

using (var context = new MusicPlayerContext())
{
    Console.WriteLine("Save PlayList 2 (in context add)");
    context.Playlists.Attach(playlist3);
    playlist3.PlaylistEntries.Add(new PlaylistEntry { 
      FilePath = "Entry3", 
      PlaylistId = playlist3.PlaylistId, PlaylistEntryId = 3 
    });
    context.SaveChanges();
}

... OR 在附加父对象后标记两个对象条目。

using (var context = new MusicPlayerContext())
{
    Console.WriteLine("Save PlayList 2 (full attach)");
    context.Playlists.Attach(playlist2);
    context.Entry(playlist2).State = EntityState.Modified;
    context.Entry(playlist2.PlaylistEntries.First()).State = EntityState.Added;
    context.SaveChanges();
}

在两种情况下,当SaveChanges()出现时,Entity Framework现在都知道在数据库中做什么。

DotNetFiddle

答案 1 :(得分:0)

只要仅在添加context.SaveChanges();而不添加PlayList之后调用PlaylistEntries,Entity Framework就会将命令发送到数据库并重置上下文状态。因此,在此之后将PlaylistEntries添加到PlayList不会产生任何效果。要在PlaylistEntries中插入Playlist,请编写如下代码:

var playlist = new Playlist { Name = "My first playlist" };
using (var context = new MusicPlayerContext(stringBuilder))
{
    playlist.PlaylistEntries.Add(new PlaylistEntry { FilePath = "lkdfj", PlaylistId = playlist.PlaylistId }); // Even you don't need to specify `PlaylistId` here. EF can map it.
    context.Playlists.Add(playlist);
    context.SaveChanges();
}

希望这对您有用。

答案 2 :(得分:0)

我已决定像其他答案所建议的那样,从上下文中向列表中添加新条目。如果有人仍然想知道如何使它在分离状态下工作,请按以下步骤操作:

var playlist = new Playlist { Name = "My first playlist" };

using (var context = new MusicPlayerContext(stringBuilder))
{
    context.Playlists.Add(playlist);
}

playlist.PlaylistEntries.Add(new PlaylistEntry { FilePath = "Song7" });
playlist.PlaylistEntries.Add(new PlaylistEntry { FilePath = "Song8" });

using (var context = new MusicPlayerContext(stringBuilder))
{
    context.Playlists.Add(playlist);
    context.Entry(playlist).State = EntityState.Modified;

    foreach (var entry in playlist.PlaylistEntries)
    {
        context.Entry(entry).State = entry.PlaylistEntryId == 0 ? EntityState.Added : EntityState.Modified;
    }

    context.SaveChanges();
}

using (var context = new MusicPlayerContext(stringBuilder))
{
    context.Playlists.Include(x => x.PlaylistEntries).ToList();
}

context.Playlists.Add(playlist)实际上并未添加新的播放列表。据我了解,它附加了播放列表及其上的所有新条目。如果我不使用添加,则会收到错误消息,因为默认情况下新条目的PlaylistEntryID都设置为0。