Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/standard/data/sqlite/database-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ Consider carefully how your app will handle these errors.

## Locking, retries, and timeouts

> [!WARNING]
> Although SQLite supports concurrent access to the same database from multiple threads, the .NET APIs objects are not thread-safe. This means that `SqliteConnection`, `SqliteCommand` and `SqliteDataReader` cannot be shared and used concurrently from multiple threads.
> When using Microsoft.Data.Sqlite from a concurrent application, simply create and open a new instance of `SqliteConnection` whenever you need to access the database (pooling ensures that this is a fast operation).
SQLite is aggressive when it comes to locking tables and database files. If your app enables any concurrent database access, you'll likely encounter busy and locked errors. You can mitigate many errors by using [write-ahead logging](async.md).

Whenever Microsoft.Data.Sqlite encounters a busy or locked error, it will automatically retry until it succeeds or the command timeout is reached.
Expand Down
133 changes: 68 additions & 65 deletions samples/snippets/standard/data/sqlite/HelloWorldSample/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,79 +8,82 @@ class Program
{
static void Main()
{
using (var connection = new SqliteConnection("Data Source=hello.db"))
CreateAndSeed();
Query();

// Clean up
SqliteConnection.ClearAllPools();
File.Delete("hello.db");
}

static void CreateAndSeed()
{
using var connection = new SqliteConnection("Data Source=hello.db");

connection.Open();

var command = connection.CreateCommand();
command.CommandText = """
CREATE TABLE user (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);
INSERT INTO user
VALUES (1, 'Brice'),
(2, 'Alexander'),
(3, 'Nate');
""";
command.ExecuteNonQuery();

Console.Write("Name: ");
var name = Console.ReadLine();

#region snippet_Parameter
command.CommandText = "INSERT INTO user (name) VALUES ($name)";
command.Parameters.AddWithValue("$name", name);
#endregion
command.ExecuteNonQuery();

command.CommandText = "SELECT last_insert_rowid()";
var newId = (long)command.ExecuteScalar()!;

Console.WriteLine($"Your new user ID is {newId}.");
}

static void Query()
{
Console.Write("User ID: ");
var line = Console.ReadLine();
if (line is null)
{
connection.Open();

var command = connection.CreateCommand();
command.CommandText =
@"
CREATE TABLE user (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL
);
INSERT INTO user
VALUES (1, 'Brice'),
(2, 'Alexander'),
(3, 'Nate');
";
command.ExecuteNonQuery();

Console.Write("Name: ");
var name = Console.ReadLine();

#region snippet_Parameter
command.CommandText =
@"
INSERT INTO user (name)
VALUES ($name)
";
command.Parameters.AddWithValue("$name", name);
#endregion
command.ExecuteNonQuery();

command.CommandText =
@"
SELECT last_insert_rowid()
";
var newId = (long)command.ExecuteScalar();

Console.WriteLine($"Your new user ID is {newId}.");
return;
}

Console.Write("User ID: ");
var id = int.Parse(Console.ReadLine());
var id = int.Parse(line);

#region snippet_HelloWorld
using (var connection = new SqliteConnection("Data Source=hello.db"))
using var connection = new SqliteConnection("Data Source=hello.db");

connection.Open();

using var command = connection.CreateCommand();
command.CommandText = """
SELECT name
FROM user
WHERE id = $id
""";
command.Parameters.AddWithValue("$id", id);

using var reader = command.ExecuteReader();

while (reader.Read())
{
connection.Open();

var command = connection.CreateCommand();
command.CommandText =
@"
SELECT name
FROM user
WHERE id = $id
";
command.Parameters.AddWithValue("$id", id);

using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
var name = reader.GetString(0);

Console.WriteLine($"Hello, {name}!");
}
}
var name = reader.GetString(0);

Console.WriteLine($"Hello, {name}!");
}
#endregion

// Clean up
SqliteConnection.ClearAllPools();
File.Delete("hello.db");
}
}
}
Loading