Rewrite DB layer to use a Dapper provider abstraction (MySQL + SQLite)#11
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replace static Database callbacks with WeaponStore async calls. Core.InitializeDatabase uses DatabaseProviderFactory; Utils.AddPlayerToList and RemovePlayerFromList use Task.Run + Server.NextFrame for threading safety. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Guards the Server.NextFrame callback in AddPlayerToList so weapon preferences from an in-flight async DB load are not written into a Player that already left (and whose slot may have been reused). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaces concatenated string SQL with C# """ raw string literals in WeaponStore CRUD and both providers' CREATE TABLE DDL. No behavior change; verified by the existing SQLite provider + WeaponStore tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Collapse the if-null-throw block into a ?? throw expression when assigning RetakesPluginEventSender.
…ng helper Deletes Modules/Database.cs (fully superseded by WeaponStore + the provider abstraction) and the now-unused Config.BuildConnectionString() whose only caller was the old Database.Connect. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- AddPlayerToList: skip players whose Steam authorization isn't ready yet (prevents an AuthorizedSteamID null deref during map start / hot reload); they are added later via OnClientAuthorized. - ConnectionConfig.IsValid: accept port 65535 (was excluded by a strict < bound). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a GitHub Actions workflow that restores, builds the plugin in Release, and runs the xUnit test suite on .NET 8. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ravid-A
added a commit
that referenced
this pull request
Jun 8, 2026
Rewrite DB layer to use a Dapper provider abstraction (MySQL + SQLite)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Rewrites the plugin's database layer to use a provider abstraction over Dapper, with swappable MySQL/MariaDB and SQLite backends selected via config, and replaces the old callback/
MySqlDataReaderAPI with async/await + parameterized queries.The old
Databaseclass (static, MySQL-only, interpolated SQL passed to callback delegates) is gone. SQL injection vectors from string interpolation are eliminated.What changed
IDatabaseProvider+SqliteProvider/MySqlProvider— engine-specific connection creation andCREATE TABLEDDL only.WeaponStore— engine-agnostic async, parameterized CRUD (InitializeAsync,GetUserAsync,CreateUserAsync,SaveUserAsync) over Dapper. SQL is written as C#"""raw string literals.DatabaseProviderFactory— builds the provider from config; resolves relative SQLite paths against the plugin module directory.Provider("mysql"default /"sqlite") andSqlitePathfields with provider-branchedIsValid().Core/Utils— migrated to the async store with correct CounterStrikeSharp thread marshaling: SteamID/name read on the game thread, DB work on aTask.Run, results applied viaServer.NextFrame. Disconnect-during-load and unauthorized-player races are guarded. Plugin unload flushes saves synchronously.WeaponStoreCRUD (incl. a SQL-injection safety test), and the factory/config validation.Provider/SqlitePathconfig with MySQL and SQLite examples.Also included: a couple of small robustness fixes surfaced in review (skip players before Steam auth completes; accept port 65535) and an unrelated
RetakeCapability.csnull-check simplification.Behavior parity
Weapon-index clamping, insert-on-first-seen, update-on-leave, and the
give_awpint↔enum round trip are all preserved.Testing
dotnet build RetakesAllocator.csproj -c Release→ succeeds, 0 warnings.dotnet test→ 11/11 passing.