-
Notifications
You must be signed in to change notification settings - Fork 0
Database Schema
This document describes the database schema for the MatchBy application.
The database uses PostgreSQL with Entity Framework Core as the ORM. The schema follows a relational model with proper foreign key relationships and indexes.
Main user table that extends ASP.NET Core Identity's IdentityUser with additional properties.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | User identifier |
UserName |
string | Username |
NormalizedUserName |
string | Normalized username (for case-insensitive lookups) |
Email |
string | Email address |
NormalizedEmail |
string | Normalized email (for case-insensitive lookups) |
EmailConfirmed |
bool | Email confirmation status |
PasswordHash |
string | Hashed password |
SecurityStamp |
string | Security stamp for token validation |
ConcurrencyStamp |
string | Concurrency token for optimistic locking |
PhoneNumber |
string? | Phone number |
PhoneNumberConfirmed |
bool | Phone number confirmation status |
TwoFactorEnabled |
bool | Two-factor authentication enabled |
LockoutEnd |
DateTime? | Lockout end timestamp |
LockoutEnabled |
bool | Lockout enabled flag |
AccessFailedCount |
int | Failed login attempt count |
DisplayName |
string | User's display name |
PreferredSports |
integer[] | Array of preferred sports (stored as PostgreSQL array) |
BaseLocation_Latitude |
double? | Base location latitude |
BaseLocation_Longitude |
double? | Base location longitude |
BaseLocation_City |
string? | Base location city |
BaseLocation_Country |
string? | Base location country |
Bio |
string? | User biography |
Rating |
float | Average player rating |
Status |
integer | Account status (enum: AccountStatus) |
ProfileImage_Url |
string? | Profile image URL |
ProfileImage_ExpireDateTimeUtc |
DateTime? | Profile image expiration |
ProfileImage_Key |
string? | S3 storage key |
ProfileImage_FileCategory |
integer? | File category (enum) |
ProfileImage_FileType |
integer? | File type (enum) |
ProfileImage_CreatedAtUtc |
DateTime? | Profile image creation timestamp |
CreatedAtUtc |
DateTime | Account creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- One-to-Many:
Matches(as Creator) - Many-to-Many:
Matches(as Participant via MatchParticipants) - One-to-Many:
PlayerRatings(as Sender/SentById) - One-to-Many:
PlayerRatings(as Receiver/ReceivedById) - One-to-Many:
Friends(as Sender) - One-to-Many:
Friends(as Receiver) - One-to-Many:
AspNetUserClaims - One-to-Many:
AspNetUserLogins - Many-to-Many:
AspNetRoles(via AspNetUserRoles) - One-to-Many:
AspNetUserTokens
Role management table for ASP.NET Identity.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Role identifier |
Name |
string | Role name |
NormalizedName |
string | Normalized role name (for case-insensitive lookups) |
ConcurrencyStamp |
string | Concurrency token for optimistic locking |
Relationships:
- One-to-Many:
AspNetRoleClaims - Many-to-Many:
AspNetUsers(via AspNetUserRoles)
Claims associated with roles.
| Column | Type | Description |
|---|---|---|
Id |
integer (PK) | Claim identifier (auto-increment) |
RoleId |
string (FK) | Role identifier |
ClaimType |
string? | Claim type |
ClaimValue |
string? | Claim value |
Relationships:
- Many-to-One:
AspNetRoles
Claims associated with users.
| Column | Type | Description |
|---|---|---|
Id |
integer (PK) | Claim identifier (auto-increment) |
UserId |
string (FK) | User identifier |
ClaimType |
string? | Claim type |
ClaimValue |
string? | Claim value |
Relationships:
- Many-to-One:
AspNetUsers
External login providers for users (e.g., Google, Facebook).
| Column | Type | Description |
|---|---|---|
LoginProvider |
string (PK) | Login provider name |
ProviderKey |
string (PK) | Provider-specific key |
ProviderDisplayName |
string? | Display name for the provider |
UserId |
string (FK) | User identifier |
Relationships:
- Many-to-One:
AspNetUsers
Junction table for user-role relationships (many-to-many).
| Column | Type | Description |
|---|---|---|
UserId |
string (PK, FK) | User identifier |
RoleId |
string (PK, FK) | Role identifier |
Relationships:
- Many-to-One:
AspNetUsers - Many-to-One:
AspNetRoles
Authentication tokens for users (e.g., password reset tokens, 2FA tokens).
| Column | Type | Description |
|---|---|---|
UserId |
string (PK, FK) | User identifier |
LoginProvider |
string (PK) | Login provider name |
Name |
string (PK) | Token name |
Value |
string? | Token value |
Relationships:
- Many-to-One:
AspNetUsers
Represents a sports match/game.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Match identifier |
Location_Latitude |
double | Match location latitude |
Location_Longitude |
double | Match location longitude |
Location_City |
string | Match location city |
Location_Country |
string | Match location country |
Address |
string | Physical address |
MatchDateTimeUtc |
DateTime | Scheduled match date and time |
Description |
string | Match description |
minPlayers |
integer | Minimum number of players required |
maxPlayers |
integer | Maximum number of players allowed |
Sport |
integer | Sport type (enum: Sports) |
Status |
integer | Match status (enum: MatchStatus) |
Privacy |
integer | Privacy level (enum: MatchPrivacy) |
CreatorId |
string (FK) | User who created the match |
ConversationId |
string? | Associated conversation/chat |
CreatedAtUtc |
DateTime | Match creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- Many-to-One:
AspNetUsers(Creator) - Many-to-Many:
AspNetUsers(Participants via MatchParticipants) - One-to-One:
Conversation(optional) - One-to-Many:
MatchInvite - One-to-Many:
PlayerRatings
Represents a team that can participate in matches.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Team identifier |
Name |
string | Team name |
Description |
string | Team description |
OwnerId |
string (FK) | User who owns/created the team |
ConversationId |
string? | Associated conversation/chat |
CreatedAtUtc |
DateTime | Team creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- Many-to-One:
AspNetUsers(Owner) - Many-to-Many:
AspNetUsers(Members via TeamMembers) - One-to-One:
Conversation(optional) - One-to-Many:
TeamInvite
Represents a chat conversation (can be associated with a match, team, or be private).
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Conversation identifier |
Type |
integer | Conversation type (enum: ConversationType - Private, Team, Match) |
Title |
string? | Conversation title |
Image_Url |
string? | Conversation image URL |
Image_ExpireDateTimeUtc |
DateTime? | Image expiration |
Image_Key |
string? | S3 storage key |
Image_FileCategory |
integer? | File category (enum) |
Image_FileType |
integer? | File type (enum) |
Image_CreatedAtUtc |
DateTime? | Image creation timestamp |
CreatorId |
string (FK) | User who created the conversation |
TeamId |
string? (FK) | Associated team (if any) |
MatchId |
string? (FK) | Associated match (if any) |
LastMessageContent |
string? | Content of the last message |
LastMessageAtUtc |
DateTime? | Timestamp of the last message |
CreatedAtUtc |
DateTime | Conversation creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- Many-to-One:
AspNetUsers(Creator) - One-to-One:
Match(optional) - One-to-One:
Team(optional) - One-to-Many:
ChatMessage - Many-to-Many:
AspNetUsers(Participants via ConversationParticipants)
Represents a message in a conversation.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Message identifier |
Content |
string? | Message content (nullable for location messages) |
SenderId |
string (FK) | User who sent the message |
Location_Latitude |
double? | Location latitude (if message type is Location) |
Location_Longitude |
double? | Location longitude (if message type is Location) |
Location_City |
string? | Location city |
Location_Country |
string? | Location country |
InviteUrl |
string? | Invitation URL (if message contains invite) |
ReplyToMessageId |
string? (FK) | ID of message being replied to |
ConversationId |
string (FK) | Parent conversation |
CreatedAtUtc |
DateTime | Message creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- Many-to-One:
Conversation - Many-to-One:
AspNetUsers(Sender) - Many-to-One:
ChatMessage(ReplyToMessage - self-referencing)
Represents a friendship relationship between users.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Friendship identifier |
SenderId |
string (FK) | User who sent the friend request |
ReceiverId |
string (FK) | User who received the friend request |
CreatedAtUtc |
DateTime | Friendship creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- Many-to-One:
AspNetUsers(Sender) - Many-to-One:
AspNetUsers(Receiver)
Represents a rating given by one user to another.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Rating identifier |
SentById |
string (FK) | User who gave the rating |
ReceivedById |
string (FK) | User who received the rating |
MatchId |
string (FK) | Associated match |
Rating |
float | Rating value (typically 1-5) |
CreatedAtUtc |
DateTime | Rating creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- Many-to-One:
AspNetUsers(SentBy) - Many-to-One:
AspNetUsers(ReceivedBy) - Many-to-One:
Match
Represents an invitation to join a match.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Invitation identifier |
MatchId |
string (FK) | Target match |
Content |
string | Invitation message content |
SenderId |
string (FK) | User who sent the invitation |
ReceiverId |
string (FK) | User who received the invitation |
CreatedAtUtc |
DateTime | Invitation creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- Many-to-One:
Match - Many-to-One:
AspNetUsers(Sender) - Many-to-One:
AspNetUsers(Receiver)
Represents an invitation to join a team.
| Column | Type | Description |
|---|---|---|
Id |
string (PK) | Invitation identifier |
TeamId |
string (FK) | Target team |
Content |
string | Invitation message content |
SenderId |
string (FK) | User who sent the invitation |
ReceiverId |
string (FK) | User who received the invitation |
CreatedAtUtc |
DateTime | Invitation creation timestamp |
UpdatedAtUtc |
DateTime? | Last update timestamp |
DeletedAtUtc |
DateTime? | Soft delete timestamp |
Relationships:
- Many-to-One:
Team - Many-to-One:
AspNetUsers(Sender) - Many-to-One:
AspNetUsers(Receiver)
- Football
- Basketball
- Tennis
- Volleyball
- (Additional sports as needed)
- Pending
- Confirmed
- InProgress
- Completed
- Cancelled
- Public
- Private
- FriendsOnly
- Active
- Suspended
- Deleted
- Text
- Location
- Image
- (Additional types as needed)
- Sent
- Delivered
- Read
- Pending
- Accepted
- Declined
- Blocked
- Pending
- Accepted
- Declined
- Expired
{
"Latitude": 59.3293,
"Longitude": 18.0686,
"City": "Stockholm",
"Country": "Sweden"
}{
"Url": "https://...",
"ExpireDateTimeUtc": "2025-12-31T23:59:59Z",
"Key": "s3-key",
"FileCategory": "ProfileImage",
"FileType": "Image",
"CreatedAtUtc": "2025-01-01T00:00:00Z"
}Junction table for many-to-many relationship between Matches and Users (participants).
| Column | Type | Description |
|---|---|---|
MatchId |
string (PK, FK) | Match identifier |
ParticipantsId |
string (PK, FK) | User identifier |
Junction table for many-to-many relationship between Teams and Users (members).
| Column | Type | Description |
|---|---|---|
MembersId |
string (PK, FK) | User identifier |
TeamId |
string (PK, FK) | Team identifier |
Junction table for many-to-many relationship between Conversations and Users (participants).
| Column | Type | Description |
|---|---|---|
ConversationId |
string (PK, FK) | Conversation identifier |
ParticipantsId |
string (PK, FK) | User identifier |
The following indexes are created automatically by Entity Framework Core:
- All tables have primary key indexes
-
IX_AspNetRoleClaims_RoleIdon AspNetRoleClaims -
IX_AspNetUserClaims_UserIdon AspNetUserClaims -
IX_AspNetUserLogins_UserIdon AspNetUserLogins -
IX_AspNetUserRoles_RoleIdon AspNetUserRoles -
IX_Matches_CreatorIdon Matches -
IX_MatchInvites_MatchId,IX_MatchInvites_SenderId,IX_MatchInvites_ReceiverIdon MatchInvites -
IX_MatchParticipants_ParticipantsIdon MatchParticipants -
IX_PlayerRatings_MatchId,IX_PlayerRatings_SentById,IX_PlayerRatings_ReceivedByIdon PlayerRatings -
IX_Teams_OwnerIdon Teams -
IX_TeamInvites_TeamId,IX_TeamInvites_SenderId,IX_TeamInvites_ReceiverIdon TeamInvites -
IX_TeamMembers_TeamIdon TeamMembers -
IX_Friends_SenderId_ReceiverId,IX_Friends_ReceiverIdon Friends -
IX_Conversations_CreatorId,IX_Conversations_MatchId,IX_Conversations_TeamIdon Conversations -
IX_ConversationParticipants_ParticipantsIdon ConversationParticipants -
IX_ChatMessages_ConversationId,IX_ChatMessages_SenderId,IX_ChatMessages_ReplyToMessageIdon ChatMessages
-
RoleNameIndexon AspNetRoles (NormalizedName) -
UserNameIndexon AspNetUsers (NormalizedUserName) -
IX_AspNetUsers_Emailon AspNetUsers (Email) -
IX_AspNetUsers_UserNameon AspNetUsers (UserName) -
IX_Conversations_MatchId(unique) on Conversations -
IX_Conversations_TeamId(unique) on Conversations -
IX_Friends_SenderId_ReceiverId(unique) on Friends
Several tables implement soft deletes using DeletedAtUtc:
-
AspNetUsers(ApplicationUser) MatchesTeamsChatMessagesFriendsMatchInvitesTeamInvitesPlayerRatingsConversations
Soft-deleted records are not physically removed but marked with a deletion timestamp. Queries should filter out soft-deleted records using WHERE DeletedAtUtc IS NULL.
Database migrations are managed using Entity Framework Core Migrations:
# Create a new migration
dotnet ef migrations add <MigrationName>
# Apply migrations
dotnet ef database update
# Remove last migration
dotnet ef migrations removeMigrations are located in MatchBy/MatchBy/Data/Migrations/.
Database seeding is handled by seeders in MatchBy/MatchBy/Data/Seeders/:
-
UserSeeder- Creates test users -
MatchSeeder- Creates sample matches -
TeamSeeder- Creates sample teams -
ConversationSeeder- Creates sample conversations -
ChatMessageSeeder- Creates sample messages - Additional seeders as needed
Seeders run automatically in Development environment.
- Home - Main documentation index
- Architecture - System architecture