【问题标题】:Entity is incorrectly detaching from tracking EF Core实体错误地从跟踪 EF Core 中分离
【发布时间】:2022-01-04 23:17:17
【问题描述】:

我正在尝试从数据库中查询对象,遍历它们并检查列是否有值,如果没有,则创建一个值并将其分配给该列并将其保存到数据库中。我遇到的问题是实体在查询后分离,因此我无法保存更改。下面是我用来查询和更新实体的代码。

    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),但据我所知,记录的查询甚至没有拆分)

【问题讨论】:

    标签: c# entity-framework entity-framework-core npgsql


    【解决方案1】:

    您与projected objects合作

    • 播放列表数据
    • 视频数据

    据我所知,EF 核心不跟踪投影对象。所以解决方案是选择 DbSet 的实体对象(指在database.PlaylistsAddedplaylist.Videos 属性中指定的类型)或在更新之前选择这些对象然后更新它们。

    更新:

    第二个选项的示例代码:

    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;
        }
    }
    

    注意:这会产生双重选择,所以第一个选项更受欢迎

    【讨论】:

    • 是的,这就是为什么,您的第一种方法基本上是正确的,只是我已经在使用 DbSet 类型,只是通过投影。我将查询更改为List&lt;PlaylistData&gt; pld = await database.PlaylistsAdded.Include(playlist =&gt; playlist.Videos.Where( video =&gt; (video.WeeklyPlaylistItemId == null || video.WeeklyPlaylistItemId.Length == 0) &amp;&amp; startOfWeek &lt;= video.TimeSubmitted)).ToListAsync().ConfigureAwait(false);,现在它可以正常运行了,谢谢!我想在不查询整行的情况下有效地做到这一点的唯一方法是自己进行更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-09
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多