更新语句,删除导航属性记录

时间:2019-09-17 03:22:06

标签: postgresql entity-framework-core

我正在使用EF Core将新游戏添加到正在构建的Sudoku API中。每个游戏都有一个可以担任多个角色的用户。每当我添加新游戏时,我都必须手动拉用户角色并将其添加回上下文中,否则它们将丢失。同样,当我添加新游戏时,可能会丢失用户所有其他先前的游戏。我在做什么错了?

我尝试过

_context.Games.Add(game);

这导致了一系列问题,然后我尝试了

_context.Games.Update(game);

但我遇到了当前问题:

        public async Task<Game> CreateGame(CreateGameRO createGameRO) {

            var userActionResult = 
                await _userService.GetUser(createGameRO.UserId);
            var difficultyActionResult = 
                await _difficultiesService.GetDifficulty(createGameRO.DifficultyId);

            SudokuMatrix matrix = new SudokuMatrix();
            matrix.GenerateSolution();

            Game game = new Game(
                userActionResult.Value, 
                matrix, 
                difficultyActionResult.Value);

            // EF Core loses reference to the users roles when creating new games.
            // Before we save the new game we pull a reference to the users roles...
            var user = game.User;
            var userRoles = _context.UsersRoles.Where(u => u.UserId == user.Id).ToList();
            //var userGames = _context.Games.Where(g => g.UserId == user.Id).ToList();

            _context.Games.Update(game);
            await _context.SaveChangesAsync();

            // ...then we reattach the users roles to the data context.
            _context.UsersRoles.AddRange(userRoles);
            //_context.Games.AddRange(userGames);
            await _context.SaveChangesAsync();

            return game;
        }

我在应用程序中添加了日志记录,并注意到以下生成的SQL命令:

      DELETE FROM "Games"
      WHERE "Id" = @p0;
      DELETE FROM "Games"
      WHERE "Id" = @p1;
      DELETE FROM "SudokuCells"
      WHERE "Id" = @p2;
      DELETE FROM "SudokuCells"
      WHERE "Id" = @p3;
      DELETE FROM "SudokuCells"
      WHERE "Id" = @p4;

发生这种情况的情况如下...假设我创建了一个用户Dean Winchester,然后添加了另一个用户Sam Winchester。然后为Dean创建两个新游戏,一切都很好,为Sam创建两个新游戏,一切都还不错...然后为Dean创建另一个游戏,并创建上面的SQL,并删除前两个游戏。 / p>

1 个答案:

答案 0 :(得分:0)

由于没有其他人可以回答这个问题,因此我将继续这样做。

据推测,我正在使用WebAPI在不连接的环境中工作,除非我特别跟踪它们,否则上下文不了解用户的其他游戏和角色。但是,我已经在日志中记录了EF核心消失的证据,这是跟踪用户游戏和角色的方式...并删除它们!

这种行为对我来说毫无意义,如果有人可以解释以这种方式处理它的基本逻辑,我将不胜感激。对我来说,更新语句封装了删除是很直观的。

我的解决方案现在看起来像这样:

            Game game = new Game(
                userActionResult.Value, 
                matrix, 
                difficultyActionResult.Value);

            var user = await _context.Users
                .FirstOrDefaultAsync(u => u.Id == userActionResult.Value.Id);

            var userRoles = await _context.UsersRoles
                .Where(ur => ur.UserId == user.Id)
                .ToListAsync();

            var userGames = await _context.Games
                .Where(g => g.UserId == user.Id)
                .ToListAsync();

            _context.Games.Update(game);
            await _context.SaveChangesAsync();

            _context.UsersRoles.AddRange(userRoles);
            await _context.SaveChangesAsync();

            _context.Games.UpdateRange(userGames);
            await _context.SaveChangesAsync();

我必须三遍数据库,以保护我一开始就不想接触的数据……这很愚蠢,但是可以。

我对这种解决方案不满意。假设一个用户玩了1000场游戏?我必须将所有1000场比赛拉入内存...添加我的新游戏... EF核心然后删除所有先前的1000场比赛...然后我必须重新添加1000场比赛?