I am developing multitenant SaaS based application and going with Shared Database for storing all the tenant records with help of TenantId column.
Now the problem is i have some list of lookup records that needs to be shared for all the tenants. For example list of games.
GamesTable
Id
GameName
Also have another table used for storing only tenant specific records
TenantGames
Id
TenantId
GameName
The basic need is i want to use both table data and get the necessary details (Game_Name) while joining with another transaction table like UserGames. How can i achive this with this design? Here Game_Name can be either referred from Games Shared table or TenantSpecificGames table
Is there any other DB design which allows me to do mix both common master data and tenant master data with JOIN?
Basic requirement is keep common data and allow customization for the tenants if they want to add any new items.
This is the design I would then use.
Games
Id
GameName
IsTenantSpecific
SomeGameSpecificColumn
TenantGames
GameId
TenantId
SomeTenantSpecificColumn
AnotherTenantSpecificColumn
Then you can query that table in a Join with:
...
FROM
Games
INNER JOIN UserGames ON
UserGames.GameId = Games.Id
LEFT JOIN TenantGames ON
TenantGames.GameId = Games.Id
WHERE
TenantGames.TenantId = @tenantId OR
(
TenantGames.TenantId IS NULL AND
IsTenantSpecific = 0
)
Game specific fields can be put in the Games table. Tenant specific fields can be added to the TenantGames table, and those fields will be NULL if it is not a tenant specific customization.
We have a saas based database and we keep common data and tenant data in the same table.
Concept
GamesTable
Id NOT NULL
TenantId NULL
GameName NOT NULL
Add a unique key for TenantId and GameName
- if TenantId is NULL you know it is common data
- if TenantId is NOT NULL you know it belongs to a specific tenant and who exactly.
"Is there any other DB design which allows me to do mix both common
master data and tenant master data with JOIN?"
Yes
SELECT *
FROM GamesTable where TenantId = 'your tenant id'
UNION
SELECT *
FROM GamesTable where TenantId IS NULL -- common
This is a classic example of "many to many".
Table: Games
------------
GameID
GameName
IsMasterGame
TennantGames
------------------
GameID
TennantID
Tennants
------------
TennantID
...
To get the games for a given tennant, you would run a query like:
select *
from Games
where isMasterGame = true
union
select *
from Games g,
TennantGames tg
where g.GameID = tg.GameID
and isMasterGame = false
and tg.TennantID = $currentTennant
(Apologies for archaic join syntax)
The union allows you to ask two questions: which games apply to everyone (isMasterGame = true
), and secondly which games apply to the current tennant (tg.TennantID = $currentTennant
). Logically, tennant games cannot also be master games.
You can merge the tables leaving TenantId as NULL for records you wish to not be Tenant specific.
Games
Id
TenantId
GameName
The you can query that table in a Join with:
...
FROM
Games
INNER JOIN UserGames ON
UserGames.GameId = Games.Id
WHERE
Games.TenantId = @tenantId OR
Games.TenantId IS NULL
This will save you the trouble of ensuring that the Id is unique between the tables, unless you are using a UNIQUEIDENTIFIER for the Id.