How v2rayN Handles SQLite Database Storage for Profiles and Settings
v2rayN uses a singleton SQLiteHelper class to manage a local SQLite database file named guiNDB.db, providing both synchronous and asynchronous CRUD operations for all user data including proxy profiles, subscriptions, routing rules, and traffic statistics.
v2rayN persists all runtime user data in a lightweight SQLite database rather than flat files or the Windows registry. This design centralizes data management through a singleton helper pattern, ensuring thread-safe access and consistent data integrity across application restarts. The storage layer handles everything from proxy server configurations to real-time traffic statistics and custom routing rules.
Database Architecture and File Location
The database layer centers on the SQLiteHelper singleton located in v2rayN/ServiceLib/Helper/SqliteHelper.cs. This helper encapsulates both a synchronous SQLiteConnection and an asynchronous SQLiteAsyncConnection pointing to guiNDB.db in the user's configuration folder.
The helper exposes standardized CRUD methods including InsertAsync, InsertAllAsync, ReplaceAsync, UpdateAsync, UpdateAllAsync, DeleteAsync, ExecuteAsync, QueryAsync, and TableAsync. This abstraction allows UI components and manager classes to interact with the database without handling low-level ADO.NET operations directly.
Database Initialization and Table Creation
During application startup, AppManager.InitApp() in v2rayN/ServiceLib/Manager/AppManager.cs initializes the database schema by creating tables for all persistent entities:
SQLiteHelper.Instance.CreateTable<SubItem>();
SQLiteHelper.Instance.CreateTable<ProfileItem>();
SQLiteHelper.Instance.CreateTable<ServerStatItem>();
SQLiteHelper.Instance.CreateTable<RoutingItem>();
SQLiteHelper.Instance.CreateTable<ProfileExItem>();
SQLiteHelper.Instance.CreateTable<DNSItem>();
SQLiteHelper.Instance.CreateTable<FullConfigTemplateItem>();
#pragma warning disable CS0618
SQLiteHelper.Instance.CreateTable<ProfileGroupItem>();
#pragma warning restore CS0618
This initialization runs every time the application starts, ensuring that new installations have all required tables while existing databases remain unaffected.
Data Models and Entity Structure
v2rayN uses Plain Old CLR Objects (POCOs) decorated with SQLite attributes to define the schema. Each model maps to a specific table in guiNDB.db:
| Model | Purpose | Source File |
|---|---|---|
ProfileItem |
Proxy server configurations (address, port, protocol, security settings) | v2rayN/ServiceLib/Models/ProfileItem.cs |
SubItem |
Subscription URLs and metadata | v2rayN/ServiceLib/Models/SubItem.cs |
RoutingItem |
Custom routing rules and rule sets | v2rayN/ServiceLib/Models/RoutingItem.cs |
DNSItem |
Custom DNS server configurations | v2rayN/ServiceLib/Models/DNSItem.cs |
ServerStatItem |
Traffic statistics per server | v2rayN/ServiceLib/Models/ServerStatItem.cs |
ProfileExItem |
Extended runtime data (latency, speed test results, UI sort order) | v2rayN/ServiceLib/Models/ProfileExItem.cs |
FullConfigTemplateItem |
Templates for full V2Ray configuration generation | v2rayN/ServiceLib/Models/FullConfigTemplateItem.cs |
ProfileGroupItem |
Legacy grouping for policy-based routing | v2rayN/ServiceLib/Models/ProfileGroupItem.cs |
Each entity uses [PrimaryKey] attributes for unique identifiers, typically using IndexId fields as string-based GUIDs.
CRUD Operations and Data Flow
The SQLiteHelper provides a consistent async API for data manipulation. Here are the typical patterns used throughout the codebase:
Creating a new proxy profile:
var profile = new ProfileItem
{
IndexId = Guid.NewGuid().ToString(),
Remarks = "My SS Server",
ConfigType = EConfigType.Shadowsocks,
Address = "example.com",
Port = 8388,
Password = "myPassword"
};
await SQLiteHelper.Instance.InsertAsync(profile);
Reading all enabled subscriptions:
var subs = await SQLiteHelper.Instance.TableAsync<SubItem>()
.Where(s => s.Enabled)
.OrderBy(s => s.Sort)
.ToListAsync();
Updating traffic statistics in bulk:
// _lstServerStat is a List<ServerStatItem> with modified statistics
await SQLiteHelper.Instance.UpdateAllAsync(_lstServerStat);
Executing raw SQL for maintenance:
await SQLiteHelper.Instance.ExecuteAsync(
"DELETE FROM ProfileExItem WHERE indexId NOT IN (SELECT indexId FROM ProfileItem)");
Database Migration and Schema Updates
When older database versions are detected, AppManager.MigrateProfileExtra() handles schema migrations using raw SQL queries. This method reads existing rows with SQLiteHelper.Instance.QueryAsync<ProfileItem>(sql), transforms the data to match new ProtocolExtraItem structures, and persists changes using UpdateAllAsync.
This approach allows v2rayN to evolve its data model while preserving user data across application updates.
Concurrency and Performance Optimization
The database layer handles concurrency through several mechanisms:
- Async API: Most UI interactions use
SQLiteAsyncConnectionmethods to prevent blocking the main thread. - Batch Operations:
ProfileExManagerimplements a queue system (_queIndexIds) that batches changes and persists them in bulk usingInsertAllAsyncandUpdateAllAsync, reducing database write overhead. - Connection Management: The singleton pattern ensures a single shared connection pool rather than repeatedly opening and closing connections.
Application Lifecycle and Cleanup
During application shutdown, AppManager.AppExitAsync triggers cleanup routines that eventually call SQLiteHelper.Instance.DisposeDbConnectionAsync(). This method, referenced in BackupAndRestoreViewModel, safely closes both the synchronous and asynchronous database connections, ensuring data integrity and preventing corruption on exit.
Summary
- v2rayN stores all user data in a single SQLite database file named
guiNDB.dblocated in the user's configuration folder. - The
SQLiteHelpersingleton inv2rayN/ServiceLib/Helper/SqliteHelper.csprovides both synchronous and asynchronous CRUD operations. - Tables are created automatically at startup in
AppManager.InitApp()for entities likeProfileItem,SubItem,RoutingItem, andServerStatItem. - Raw SQL execution supports complex queries and database migrations, such as the
MigrateProfileExtra()method for schema updates. - Performance is optimized through async operations and batch processing in managers like
ProfileExManager. - Graceful shutdown is ensured by
DisposeDbConnectionAsync()which closes connections safely.
Frequently Asked Questions
Where does v2rayN store its SQLite database file?
v2rayN stores the database in a file named guiNDB.db within the user's configuration directory. The exact path depends on the operating system and installation type, but the SQLiteHelper class constructs the connection string to point to this specific file in the application's data folder.
How does v2rayN handle database schema updates when upgrading versions?
When the application detects an older database schema (for example, when ConfigVersion is less than 3), the AppManager.MigrateProfileExtra() method executes raw SQL queries to read existing data, transform it to match new structures like ProtocolExtraItem, and write it back using UpdateAllAsync. This ensures user data survives application updates.
Is the database access thread-safe in v2rayN?
Yes, v2rayN uses a singleton SQLiteHelper that maintains both synchronous and asynchronous connections. The UI layer primarily uses the async API (SQLiteAsyncConnection) to avoid blocking the main thread. Additionally, managers like ProfileExManager use internal queues to batch operations, preventing concurrent write conflicts.
What types of data are stored in the v2rayN SQLite database?
The database stores all persistent user configuration and runtime data, including proxy server profiles (ProfileItem), subscription URLs (SubItem), custom routing rules (RoutingItem), DNS configurations (DNSItem), traffic statistics (ServerStatItem), extended profile metadata like latency and speed test results (ProfileExItem), and configuration templates (FullConfigTemplateItem).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →