如何加强一对多的关系

发布于 2024-12-10 11:01:53 字数 590 浏览 2 评论 0原文

我正在开发一款在线多人棋盘游戏和游戏。有一个 SQL 服务器问题。

假设游戏允许两名玩家。创建游戏时,创建者将被添加为第一个用户。

此时,两个用户可以尝试同时加入游戏。应阻止其中一位用户。

我的数据库架构如下:

tbGame - contains a list of all games. PrimaryKey is GameId
tbPlayers - contains a list of all registered users. PrimaryKey is PlayerId
tbPlayersInGame - contains a list of all players in each game. Foreign key 
                  relations to tbGame and tbPlayers.

我觉得我需要两件事:

  1. 一种基于 GameId 锁定 tbPlayersInGame 的方法。这将在向游戏添加玩家时使用。根据我的阅读,听起来键范围锁(在 GameId 上)是合适的。
  2. 一种强制建立一对二关系的方法,这样添加第三个玩家的尝试就会失败。

I'm working on an online muiltiplayer board game & have a SQL server question.

Lets assume the game allows two players. When the game is created, the creator is added as the first user.

At that point, two users could try to join the game simultaneously. One of these users should be blocked.

My database schema is as follows:

tbGame - contains a list of all games. PrimaryKey is GameId
tbPlayers - contains a list of all registered users. PrimaryKey is PlayerId
tbPlayersInGame - contains a list of all players in each game. Foreign key 
                  relations to tbGame and tbPlayers.

I feel like I need two things:

  1. A way to lock tbPlayersInGame based on the GameId. This would be used while adding a player to a game. From what I've read it sounds like a key-range lock (on GameId) would be suitable.
  2. A way to enforce a 1-to-2 relationship so that attempts to add a 3rd player would fail.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

墨落成白 2024-12-17 11:01:53

一些建议:

1) 当您尝试写入 tbPlayersInGame 表时,首先执行 SELECT 以确保游戏未满,然后 INSERT INTO 表。将此 SELECT 和 INSERT INTO 包装在事务中,并将事务隔离级别设置为可序列化。

2)没有单独的 tbPlayersInGame 表,而是 tbGame 中有 2 个字段:Player1Id、Player2Id

A couple suggestions:

1) When you try to write to the tbPlayersInGame table first do a SELECT to make sure the game isn't full, then INSERT INTO the table. Wrap this SELECT and the INSERT INTO in a transaction with the transaction isolation level set to serializable.

2) Don't have a separate tbPlayersInGame table, instead have 2 fields in tbGame: Player1Id, Player2Id

呆头 2024-12-17 11:01:53

您可以将表设置为具有列 - 可能标记为 host_playervisitor_player 或必要的等效项(例如在国际象棋中 - 黑色白色)。这样做的好处是可以将有趣的事情降到最低限度,并显示出关系的自然状态。

当然,只有当玩家数量永久有限时,这才有效 - 对于大多数棋盘游戏实例,这可能会很好地工作......

如果您正在尝试制作一款游戏,其中上限是可变的(无论出于何种原因),您可以使用以下语句“检测”可用的空闲插槽:

INSERT INTO game_players (game_id, player_id) 
SELECT VALUES (:GAME_ID, :PLAYER_ID)
WHERE :MAX_PLAYER_COUNT > (SELECT COUNT(*)
                           FROM game_players
                           WHERE game_id = :GAME_ID)

如果返回错误代码 100(“未选择/更新行”),则玩家列表已满。您可能需要添加其他条件(以防止玩家加入两次),但这个概念仍然有效。

Instead of a 1-to-n relationship, you could set up your table to have to columns - probably labelled host_player and visitor_player, or the necessary equivalent (like in chess - black and white). This has the advantage of keeping funny things to a minimum, and showing the natural state of the relationship.

This of course only works if there is supposed to be a permanently limited number of players - for most instances of boardgames, this will likely work fine....

If you are attempting to make a game where the upper limit is mutable (for whatever reason), you can 'detect' free slots available with the following statement:

INSERT INTO game_players (game_id, player_id) 
SELECT VALUES (:GAME_ID, :PLAYER_ID)
WHERE :MAX_PLAYER_COUNT > (SELECT COUNT(*)
                           FROM game_players
                           WHERE game_id = :GAME_ID)

If you get back an error-code of 100 ('No rows selected/updated), the player list is full. You may need to add other conditions (to prevent players from joining twice), but the concept should still work.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文