Reputation: 3166
I have the following tables
CREATE TABLE [dbo].[User]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[Username] NVARCHAR(200) NOT NULL,
[Domain] NVARCHAR(200) NOT NULL,
[IsAdministrator] BIT NOT NULL DEFAULT 'false',
[IsGroup] BIT NULL DEFAULT 'false',
)
CREATE TABLE [dbo].[Role]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[Name] NVARCHAR(500) NOT NULL,
[Description] NVARCHAR(1000) NOT NULL,
[ResourceType] NVARCHAR(100) NOT NULL,
)
A user can be assigned one or more roles for a particular resource
For example,
Say there are 2 types of resources (Workspace
and Process
)
There will be a table for each resource type, and the schema for each resource will be different (hence I can't use a generic resource table)
CREATE TABLE [dbo].[Workspace]
(
[WorkspaceId] UNIQUEIDENTIFIER NOT NULL,
[WorkspaceName] NVARCHAR(100) NOT NULL,
[Description] NVARCHAR(500) NULL,
CONSTRAINT [UC_WorkspaceName] UNIQUE([WorkspaceName]),
CONSTRAINT [PK_Workspace] PRIMARY KEY([WorkspaceId])
)
CREATE TABLE [dbo].[Process]
(
[ProcessId] UNIQUEIDENTIFIER NOT NULL ,
[ProcessName] NVARCHAR(100) NOT NULL,
CONSTRAINT [PK_BusinessProcessId] PRIMARY KEY ([ProcessId]),
)
but irrespective of the resource type, the primary key will always be a UNIQUEIDENTIFIER
.
Each user can have one or more roles assigned for a particular ResourceId and ResourceType
CREATE TABLE [dbo].[UserRole]
(
[UserId] UNIQUEIDENTIFIER NOT NULL,
[RoleId] UNIQUEIDENTIFIER NOT NULL,
[ResourceType] NVARCHAR(100) NOT NULL,
[ResourceId] UNIQUEIDENTIFIER NOT NULL,
CONSTRAINT [PK_User_Role] PRIMARY KEY (ResourceId, UserId, RoleId, ResourceType),
CONSTRAINT [FK_UserId] FOREIGN KEY ([UserId]) REFERENCES [User]([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [Role]([Id]) ON DELETE CASCADE
)
But with this design I can't set UserRole.ResourceId
as a foreign key since it could either be WorkspaceId
from the Workspace
table or ProcessId
from Process
table.
This becomes a problem during resource deletion as I have to remove obsolete entries manually.
I know I could have 2 columns in UserRole
called WorkspaceId
and ProcessId
, setting NULL
based on resource type, but in my case the number of resource types will be quite large.
My question Is,
Is there any other way where I don't have to add a column for each new resource type or should I just go with the current design (without a foreign key)?
Upvotes: 0
Views: 191
Reputation: 1065
I would combine workspace and process into a single table, and have them link to a ResourceType table.
CREATE TABLE [dbo].[User]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[Username] NVARCHAR(200) NOT NULL,
[Domain] NVARCHAR(200) NOT NULL,
[IsAdministrator] BIT NOT NULL DEFAULT 'false',
[IsGroup] BIT NULL DEFAULT 'false',
)
CREATE TABLE [dbo].[ResourceType]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[Description] NVARCHAR(100)
)
CREATE TABLE [dbo].[Role]
(
[Id] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY,
[Name] NVARCHAR(500) NOT NULL,
[Description] NVARCHAR(1000) NOT NULL,
[ResourceType_id] UNIQUEIDENTIFIER NOT NULL
)
CREATE TABLE [dbo].[Resource]
(
[ResourceId] UNIQUEIDENTIFIER NOT NULL,
[ResourceName] NVARCHAR(100) NOT NULL,
[Description] NVARCHAR(500) NULL,
[ResourceType_id] UNIQUEIDENTIFIER NOT NULL,
CONSTRAINT [UC_ResourceName] UNIQUE([ResourceName]),
CONSTRAINT [PK_Resource] PRIMARY KEY([ResourceId])
)
CREATE TABLE [dbo].[UserRole]
(
[UserId] UNIQUEIDENTIFIER NOT NULL,
[RoleId] UNIQUEIDENTIFIER NOT NULL,
[ResourceType] NVARCHAR(100) NOT NULL,
[ResourceId] UNIQUEIDENTIFIER NOT NULL,
CONSTRAINT [PK_User_Role] PRIMARY KEY (ResourceId, UserId, RoleId, ResourceType),
CONSTRAINT [FK_UserId] FOREIGN KEY ([UserId]) REFERENCES [User]([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [Role]([Id]) ON DELETE CASCADE,
CONSTRAINT [FK_ResourceId] FOREIGN KEY ([ResourceId]) REFERENCES [Resource]([ResourceId]) ON DELETE CASCADE
)
Upvotes: 0