c# - 实体框架模型中的集合未更新
问题描述
我有几个简单的模型。一个 PlaylistEntry 模型和一个包含 PlaylistEntry 模型集合的播放列表模型。
播放列表:
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;
}
}
播放列表条目
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; }
}
当我将 PlaylistEntry 添加到处于分离状态的播放列表时,我希望当我附加并保存更改时,对 PlaylistEntries 列表的更改也将被保存。他们不保存,列表为空。
这是我的代码:
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 个小时来解决这个问题,但我终其一生都无法弄清楚。
解决方案
您缺少的功能是上下文缓存的工作方式。当您将实体(手动或通过从数据库请求实体)附加到上下文时,实体框架会监视它以进行更改并跟踪这些更改。
您已将对象添加到实体的属性中,然后将其添加到上下文中。Entity Framework 现在正在观察它的变化以做任何额外的工作。 以这种方式添加的所有对象都标记为未更改。将父级标记为已更改不会将导航属性标记为已更改。
您可以将实体添加到上下文中的属性:
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();
}
...或在附加父对象后标记两个对象条目。
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();
}
在这两种情况下,Entity Framework 现在都知道SaveChanges()
发生时在 DB 中要做什么。
推荐阅读
- laravel - 在 laravel 5.7 中将 pdf 文件作为电子邮件附件发送
- java - 通过 REST API 从 Java 下载 cognos 报告
- layout - 如何在 openfin 布局管理器中实现生成和恢复工作区?你能举一些例子吗
- html - 为什么我的页脚没有显示在页面底部?
- ios - SDWebImage 不会在真实设备上显示本地存储的图像,但会显示在模拟器中
- android - UI 上的 Android 功能切换 - 搜索设计模式
- html - 我怎样才能让我的 svg 代码多边形形状在所有屏幕上都有响应
- java - 如何将 InMemoryLeaseManager 和 -CheckpointManager 用于 Azure 事件中心?
- docker - GitLab 管道奇怪的失败,即使是在旧的、以前“绿色”的提交上
- android - 尝试使用来自 googleAccount 的人员 API 获取用户信息时出错?