postgresql - 更新语句删除导航属性记录
问题描述
我正在使用 EF Core 向我正在构建的数独 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 被创建,前两个游戏被删除。
解决方案
由于没有其他人可以回答这个问题,我将继续这样做。
假设我正在使用 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 个游戏?
推荐阅读
- php - xampp的“缩小”版本?
- javascript - 删除移动设备上的 slick.js 幻灯片
- javascript - .bat 文件以打开 chrome 转到 url 并执行 JavaScript
- php - 为多行插入第二个自动增量 ID
- php - Wordpress 有一个讨厌的重定向,不允许使用 ssl
- polymer - 如何在聚合物制作的自定义组件中测试 ajax 请求
- java - Java中的可外部化数组
- django - 'cx_Oracle.Cursor' 对象在 Django 上没有属性 'numbersAsStrings'
- c - 为什么自动完成中没有显示gets方法?
- apache-kafka - Kafka Streams - 从 KTable 中消失的值