Entity Framework
Entity Framework support is still in beta and is not suitable for production databases.
This page refers to setting up a Bitwarden instance to develop on, for instructions on testing out our EF deployments for personal use, such as Bitwarden Unified, please see the help documentation.
Background
Entity Framework (EF) is an ORM framework that acts as a wrapper around a database. It allows us to support multiple (non-MSSQL) databases without having to maintain migration and query scripts for each.
Our EF implementations currently support Postgres, MySQL, and SQLite3.
Setting Up EF Databases
The workflow here is broadly the same as with the normal MSSQL implementation: set up the docker container, configure user secrets, and run migrations against their relating databases in chronological order.
Requirements
- A working local development server
- Docker
- A way to manage user secrets in the server project - see User Secrets
- Database management software (see tools recommendations)
- The
dotnet
CLI - The
dotnet
CLI Entity Framework Core tool
You can have multiple databases configured and switch between them by changing the value of the
globalSettings:databaseProvider
user secret. You don’t have to delete your connection strings.
Database Setup
- PostgreSQL
- MySQL
- SQLite
In the dev
folder of your server repository, run
docker compose --profile postgres up
In the dev
folder of your server repository, run
docker compose --profile mysql up
Select a location for your database file. You can use the dev
folder of your server repository,
git is configured to ignore .db
files in this repository for this purpose.
User secrets
Add the following values to your API, Identity, and Admin user secrets.
- PostgreSQL
- MySQL
- SQLite
Be sure to change information like root password as needed. If you already have these secrets, make sure you update the existing values instead of creating new ones
"globalSettings:databaseProvider": "postgres",
"globalSettings:postgreSql:connectionString": "Host=localhost;Username=postgres;Password=example;Database=vault_dev;Include Error Detail=true",
Be sure to change information like root password as needed. If you already have these secrets, make sure you update the existing values instead of creating new ones
"globalSettings:databaseProvider": "mysql",
"globalSettings:mySql:connectionString": "server=localhost;uid=root;pwd=example;database=vault_dev",
Add the following values to your API, Identity, and Admin user secrets. Note, you must set the Data Source path. Use the file location selected in Database Setup
"globalSettings:databaseProvider": "sqlite",
"globalSettings:sqlite:connectionString": "Data Source=/path/to/your/server/repo/dev/db/bitwarden.db",
After making changes to your secrets.json
file, remember to run pwsh setup_secrets.ps1 -clear
so
that the changes take effect.
Migrations
- PostgreSQL
- MySQL
- SQLite
In the dev
folder run the following to update the database to the latest migration
pwsh migrate.ps1 -postgres
The -postgres
flag on migrate.ps1
will run dotnet ef
commands to perform the migrations.
In the dev
folder run the following to update the database to the latest migration
pwsh migrate.ps1 -mysql
The -mysql
flag on migrate.ps1
will run dotnet ef
commands to perform the migrations.
In the dev
folder run the following to update the database to the latest migration
pwsh migrate.ps1 -sqlite
The -sqlite
flag on migrate.ps1
will run dotnet ef
commands to perform the migrations.
You can also run migrations for all database providers at once using
pwsh migrate.ps1 -all
Optional: Verify
If you would like to verify that everything worked correctly:
- Check the database tables to make sure everything has been created
- Run the integration tests from the root of your server project using
dotnet test
.- Note: this requires a configured MSSQL database. You may also need to set up other EF providers for tests to pass.
Testing EF Changes
In your server/dev/secrets.json
file find or add this block of secrets in the root of the json
structure:
"databases:0:type": "Postgres",
"databases:0:connectionString": "Host=localhost;Username=postgres;Password=_________;Database=ef_test",
"databases:0:enabled": "true",
"databases:1:type": "Sqlite",
"databases:1:enabled": "true",
"databases:1:connectionString": "Data Source=_________",
"databases:2:type": "MySql",
"databases:2:connectionString": "server=localhost;uid=root;pwd=_________;database=ef_test",
"databases:2:enabled": "true",
"databases:3:type": "SqlServer",
"databases:3:connectionString": "Server=localhost;Database=ef_test;User Id=SA;Password=_________;Encrypt=True;TrustServerCertificate=True;",
"databases:3:enabled": "true"
The example database index + type combinations are required for the tooling to work, and to support multiple versions of the same database running tests at the same time.
This block is used for test databases for each supported provider type. These are what integration
tests will connect to. You should update the password for these connection strings to match your
existing databases if you have not already. If these settings are not present at all in your
server/dev/secrets.json
file just add them to the bottom. These settings do not go in
globalSettings
. Then run pwsh setup_secrets.ps1 -clear
to apply them to your local projects.
With connection strings applied to your projects: ensure your databases are all migrated using
pwsh server/dev/migrate.ps1 --all
. Then you can run EF tests from the
test/Infrastructure.IntegrationTest
folder using dotnet test
.