How to Connect to MariaDB from C# (.NET)
MariaDB speaks the MySQL wire protocol, so connecting from C# uses the same drivers you would use for MySQL. There is no separate "MariaDB .NET driver" worth reaching for; the practical choice is between two MySQL-compatible ADO.NET drivers, and one of them is the clear default for new code.
Driver choice
MySqlConnector (2.6.1 as of June 2026) is the recommended driver. It is a clean-room, async-first ADO.NET implementation under the MIT license, and it explicitly supports MariaDB alongside MySQL, Aurora, Azure Database for MySQL, and Percona. Its async methods are genuinely asynchronous, which matters under load.
MySql.Data (Oracle's official Connector/NET, 9.7.0 as of June 2026) also connects to MariaDB, but its history of sync-over-async implementations makes it a weaker pick for high-concurrency services. If you are starting fresh, use MySqlConnector. The two share most of the API but live in different namespaces, so you cannot mix them in the same file without aliasing.
dotnet add package MySqlConnectorA basic connection
using MySqlConnector;
var connString =
"Server=localhost;Port=3306;Database=shop;" +
"User ID=appuser;Password=secret;";
await using var conn = new MySqlConnection(connString);
await conn.OpenAsync();await using ensures the connection is returned to the pool when the scope exits. Do not hold one connection open for the life of the app; open per unit of work and let pooling do its job (more below).
Running a query
await using var cmd = conn.CreateCommand();
cmd.CommandText = "SELECT id, name FROM products WHERE price > @minPrice";
cmd.Parameters.AddWithValue("@minPrice", 100);
await using var reader = await cmd.ExecuteReaderAsync();
while (await reader.ReadAsync())
{
var id = reader.GetInt32(0);
var name = reader.GetString(1);
Console.WriteLine($"{id}: {name}");
}Always parameterize. String-concatenating user input into SQL is the classic injection hole, and the driver's parameters also handle quoting and type conversion for you.
Getting a generated key
MariaDB does not have SQL Server's OUTPUT clause or PostgreSQL's RETURNING in the same form (MariaDB does support RETURNING on INSERT since 10.5, which is a genuine option). The ADO.NET-portable way is LastInsertedId:
await using var cmd = conn.CreateCommand();
cmd.CommandText = "INSERT INTO products (name, price) VALUES (@name, @price)";
cmd.Parameters.AddWithValue("@name", "Widget");
cmd.Parameters.AddWithValue("@price", 9.99m);
await cmd.ExecuteNonQueryAsync();
long newId = cmd.LastInsertedId;If you prefer RETURNING, run it as a normal query and read the result set back, but be aware it ties your code to MariaDB 10.5+ and breaks portability to MySQL.
The utf8mb4 trap
MariaDB's legacy utf8 is a three-byte encoding that cannot store emoji or some CJK characters. Use utf8mb4 for the column charset, and the driver handles the rest. If you see Incorrect string value on insert, this is almost always the cause:
ALTER TABLE products MODIFY name VARCHAR(255)
CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;Authentication differences from MySQL
This is where MariaDB and MySQL diverge in a way that matters. MySQL 8 defaults to the caching_sha2_password auth plugin; MariaDB does not use it. MariaDB sticks with mysql_native_password and adds its own ed25519 plugin for stronger auth. So the caching_sha2_password and "Public Key Retrieval" headaches that plague MySQL 8 connections do not apply to MariaDB. If you want stronger-than-native auth on MariaDB, ed25519 is the path, and MySqlConnector supports it.
Connection pooling
Pooling is on by default and keyed by the connection string. The defaults worth knowing:
Maximum Pool Sizedefaults to 100.Minimum Pool Sizedefaults to 0.Connection Idle Timeoutdefaults to 180 seconds.
The number you actually need to coordinate is total pool size across all app instances versus MariaDB's max_connections (default 151). Five app instances each with a 100-connection pool can demand 500 connections against a server that allows 151, and you get Too many connections under load. Size pools to fit the server, or raise max_connections deliberately.
Dapper
MySqlConnector is a standard ADO.NET provider, so Dapper (2.1.79 as of June 2026) works directly:
using Dapper;
var products = await conn.QueryAsync<Product>(
"SELECT id, name, price FROM products WHERE price > @minPrice",
new { minPrice = 100 });Entity Framework Core
For EF Core, use the Pomelo provider, Pomelo.EntityFrameworkCore.MySql (9.0.0 as of June 2026), which targets both MySQL and MariaDB and builds on MySqlConnector. Declare the server version so the provider enables the right feature set:
var serverVersion = ServerVersion.AutoDetect(connString);
builder.Services.AddDbContext<AppDb>(options =>
options.UseMySql(connString, serverVersion));ServerVersion.AutoDetect opens a connection at startup to read the server version; if you want to avoid that round trip, pass an explicit MariaDbServerVersion(new Version(11, 4, 0)).
SSL
For connections over an untrusted network, set the SSL mode:
| SSL Mode | Behavior |
|---|---|
None | No encryption |
Preferred | Encrypt if the server supports it (default) |
Required | Encrypt, but do not validate the server certificate |
VerifyCA | Encrypt and validate the CA |
VerifyFull | Encrypt, validate CA and hostname |
Use VerifyFull for production connections over a public network. Required encrypts but leaves you open to man-in-the-middle, so it is not enough on its own.
var connString =
"Server=db.example.com;Database=shop;User ID=appuser;Password=secret;" +
"SSL Mode=VerifyFull;";Errors you actually hit
| Symptom | Cause | Fix |
|---|---|---|
Too many connections | Combined pool size exceeds max_connections | Reduce Maximum Pool Size or raise server max_connections |
Incorrect string value | Column is legacy utf8, not utf8mb4 | Convert column/table charset to utf8mb4 |
Access denied for user | Wrong host pattern on the grant | MariaDB grants are user@host; check the host part matches your client |
Unable to connect to any of the specified hosts | Wrong host/port or server not listening | Verify bind-address, port 3306, firewall |
| Time values off by hours | Server and client time zones differ | Store UTC; convert in app code, not in SQL |
For exploring MariaDB data and drafting queries before they go into C#, Mako connects to MariaDB with AI-powered autocomplete. Try it free at mako.ai.
Skip the terminal. Use Mako.
Connect your database, write queries with AI assistance, and import/export data in clicks. Free to start.