实体错误地从跟踪 EF Core 分离
Entity is incorrectly detaching from tracking EF Core
我正在尝试从数据库中查询对象,遍历它们并检查列是否有值,如果没有,则创建一个值并将其分配给该列并将其保存到数据库中。我遇到的问题是实体在查询后分离,所以我无法保存更改。下面是我用来查询和更新实体的代码。
DateTime runTime = passedDateTime ?? DateTime.Now;
await using DiscordDatabaseContext database = new();
DateTime startOfWeek = exactlyOneWeek ? runTime.OneWeekAgo() : runTime.StartOfWeek(StartOfWeek);
//Add if not in a Weekly Playlist already and if the video was submitted after the start of the week
List<PlaylistData> pld = await database.PlaylistsAdded.Select(playlist => new PlaylistData
{
PlaylistId = playlist.PlaylistId,
WeeklyPlaylistID = playlist.WeeklyPlaylistID,
Videos = playlist.Videos.Where(
video => (video.WeeklyPlaylistItemId == null ||
video.WeeklyPlaylistItemId.Length == 0) &&
startOfWeek <= video.TimeSubmitted)
.Select(video => new VideoData
{
WeeklyPlaylistItemId = video.WeeklyPlaylistItemId,
VideoId = video.VideoId
}).ToList()
}).ToListAsync().ConfigureAwait(false);
int count = 0;
int nRows = 0;
foreach (PlaylistData playlistData in pld)
{
if (string.IsNullOrEmpty(playlistData.WeeklyPlaylistID))
{
playlistData.WeeklyPlaylistID = await YoutubeAPIs.Instance.MakeWeeklyPlaylist().ConfigureAwait(false);
}
foreach (VideoData videoData in playlistData.Videos)
{
PlaylistItem playlistItem = await YoutubeAPIs.Instance.AddToPlaylist(videoData.VideoId, playlistId: playlistData.WeeklyPlaylistID, makeNewPlaylistOnError: false).ConfigureAwait(false);
videoData.WeeklyPlaylistItemId = playlistItem.Id;
++count;
}
}
nRows += await database.SaveChangesAsync().ConfigureAwait(false);
查询工作正常,我得到了所有相关的播放列表和视频行,它们只在指定的列中有正确的数据,并且记录的查询看起来不错,但保存不起作用并调用 database.Entry()
在任何播放列表或视频对象上显示它们都是分离的。我究竟做错了什么?集合是否以不同的方式保存?我的查询应该更改吗?是否有应该更改的初始化设置? (我在 init 上设置的唯一我觉得可能会影响它的设置是 .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)
但据我所知,记录的查询甚至没有拆分)
一起工作
- 播放列表数据
- 视频数据
据我所知,EF 核心不跟踪投影对象。所以解决方案是 select DbSet 的实体对象(指在 database.PlaylistsAdded
和 playlist.Videos
属性中指定的类型)或 select 更新之前的那些对象,然后更新它们。
更新:
第二个选项的示例代码:
foreach (PlaylistData playlistData in pld)
{
var playlist = database.PlaylistsAdded
.Include(x=> x.Videos)
.First(x => x.PlaylistId == playlistData.playlistData);
if (string.IsNullOrEmpty(playlistData.WeeklyPlaylistID))
{
playlist.WeeklyPlaylistID = await YoutubeAPIs.Instance.MakeWeeklyPlaylist().ConfigureAwait(false);
}
foreach (VideoData videoData in playlistData.Videos)
{
var video = playlist.Videos.First(x=> x.VideoId == videoData.VideoId);
PlaylistItem playlistItem = await YoutubeAPIs.Instance.AddToPlaylist(videoData.VideoId, playlistId: playlistData.WeeklyPlaylistID, makeNewPlaylistOnError: false).ConfigureAwait(false);
video.WeeklyPlaylistItemId = playlistItem.Id;
++count;
}
}
注意:这会产生双重 select,因此第一个选项更可取
我正在尝试从数据库中查询对象,遍历它们并检查列是否有值,如果没有,则创建一个值并将其分配给该列并将其保存到数据库中。我遇到的问题是实体在查询后分离,所以我无法保存更改。下面是我用来查询和更新实体的代码。
DateTime runTime = passedDateTime ?? DateTime.Now;
await using DiscordDatabaseContext database = new();
DateTime startOfWeek = exactlyOneWeek ? runTime.OneWeekAgo() : runTime.StartOfWeek(StartOfWeek);
//Add if not in a Weekly Playlist already and if the video was submitted after the start of the week
List<PlaylistData> pld = await database.PlaylistsAdded.Select(playlist => new PlaylistData
{
PlaylistId = playlist.PlaylistId,
WeeklyPlaylistID = playlist.WeeklyPlaylistID,
Videos = playlist.Videos.Where(
video => (video.WeeklyPlaylistItemId == null ||
video.WeeklyPlaylistItemId.Length == 0) &&
startOfWeek <= video.TimeSubmitted)
.Select(video => new VideoData
{
WeeklyPlaylistItemId = video.WeeklyPlaylistItemId,
VideoId = video.VideoId
}).ToList()
}).ToListAsync().ConfigureAwait(false);
int count = 0;
int nRows = 0;
foreach (PlaylistData playlistData in pld)
{
if (string.IsNullOrEmpty(playlistData.WeeklyPlaylistID))
{
playlistData.WeeklyPlaylistID = await YoutubeAPIs.Instance.MakeWeeklyPlaylist().ConfigureAwait(false);
}
foreach (VideoData videoData in playlistData.Videos)
{
PlaylistItem playlistItem = await YoutubeAPIs.Instance.AddToPlaylist(videoData.VideoId, playlistId: playlistData.WeeklyPlaylistID, makeNewPlaylistOnError: false).ConfigureAwait(false);
videoData.WeeklyPlaylistItemId = playlistItem.Id;
++count;
}
}
nRows += await database.SaveChangesAsync().ConfigureAwait(false);
查询工作正常,我得到了所有相关的播放列表和视频行,它们只在指定的列中有正确的数据,并且记录的查询看起来不错,但保存不起作用并调用 database.Entry()
在任何播放列表或视频对象上显示它们都是分离的。我究竟做错了什么?集合是否以不同的方式保存?我的查询应该更改吗?是否有应该更改的初始化设置? (我在 init 上设置的唯一我觉得可能会影响它的设置是 .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery)
但据我所知,记录的查询甚至没有拆分)
- 播放列表数据
- 视频数据
据我所知,EF 核心不跟踪投影对象。所以解决方案是 select DbSet 的实体对象(指在 database.PlaylistsAdded
和 playlist.Videos
属性中指定的类型)或 select 更新之前的那些对象,然后更新它们。
更新:
第二个选项的示例代码:
foreach (PlaylistData playlistData in pld)
{
var playlist = database.PlaylistsAdded
.Include(x=> x.Videos)
.First(x => x.PlaylistId == playlistData.playlistData);
if (string.IsNullOrEmpty(playlistData.WeeklyPlaylistID))
{
playlist.WeeklyPlaylistID = await YoutubeAPIs.Instance.MakeWeeklyPlaylist().ConfigureAwait(false);
}
foreach (VideoData videoData in playlistData.Videos)
{
var video = playlist.Videos.First(x=> x.VideoId == videoData.VideoId);
PlaylistItem playlistItem = await YoutubeAPIs.Instance.AddToPlaylist(videoData.VideoId, playlistId: playlistData.WeeklyPlaylistID, makeNewPlaylistOnError: false).ConfigureAwait(false);
video.WeeklyPlaylistItemId = playlistItem.Id;
++count;
}
}
注意:这会产生双重 select,因此第一个选项更可取