Skip to content

Commit fc94a58

Browse files
authored
Microsoft.Data.Sqlite: Document deferred transactions (#20507)
Resolves #20266
1 parent e393ded commit fc94a58

File tree

4 files changed

+91
-1
lines changed

4 files changed

+91
-1
lines changed

docs/standard/data/sqlite/transactions.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
title: Transactions
3-
ms.date: 12/13/2019
3+
ms.date: 09/08/2020
44
description: Learn how to use transactions.
55
---
66
# Transactions
@@ -30,3 +30,12 @@ Microsoft.Data.Sqlite treats the IsolationLevel passed to <xref:Microsoft.Data.S
3030
The following code simulates a dirty read. Note, the connection string must include `Cache=Shared`.
3131

3232
[!code-csharp[](../../../../samples/snippets/standard/data/sqlite/DirtyReadSample/Program.cs?name=snippet_DirtyRead)]
33+
34+
## Deferred transactions
35+
36+
Starting with Microsoft.Data.Sqlite version 5.0, transactions can be deferred. This defers the creation of the actual transaction in the database until the first command is executed. It also causes the transaction to gradually upgrade from a read transaction to a write transaction as needed by its commands. This can be useful for enabling concurrent access to the database during the transaction.
37+
38+
[!code-csharp[](../../../../samples/snippets/standard/data/sqlite/DeferredTransactionSample/Program.cs?name=snippet_DeferredTransaction)]
39+
40+
> [!WARNING]
41+
> Commands inside a deferred transaction can fail if they cause the transaction to be upgraded from a read transaction to a write transaction while the database is locked. When this happens, the application will need to retry the entire transaction.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net5.0</TargetFramework>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Microsoft.Data.Sqlite" Version="5.0.0-rc.1.20451.13" />
10+
</ItemGroup>
11+
12+
</Project>
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
using System.IO;
2+
using Microsoft.Data.Sqlite;
3+
4+
namespace DeferredTransactionSample
5+
{
6+
class Program
7+
{
8+
static void Main()
9+
{
10+
var connection = new SqliteConnection("Data Source=DeferredTransactionSample.db");
11+
connection.Open();
12+
13+
var createCommand = connection.CreateCommand();
14+
createCommand.CommandText =
15+
@"
16+
CREATE TABLE data (
17+
value INTEGER
18+
);
19+
20+
INSERT INTO data
21+
VALUES (1);
22+
";
23+
createCommand.ExecuteNonQuery();
24+
25+
#region snippet_DeferredTransaction
26+
using (var transaction = connection.BeginTransaction(deferred: true))
27+
{
28+
// Before the first statement of the transaction is executed, both concurrent
29+
// reads and writes are allowed
30+
31+
var readCommand = connection.CreateCommand();
32+
readCommand.CommandText =
33+
@"
34+
SELECT *
35+
FROM data
36+
";
37+
var value = (long)readCommand.ExecuteScalar();
38+
39+
// After a the first read statement, concurrent writes are blocked until the
40+
// transaction completes. Concurrent reads are still allowed
41+
42+
var writeCommand = connection.CreateCommand();
43+
writeCommand.CommandText =
44+
@"
45+
UPDATE data
46+
SET value = $newValue
47+
";
48+
writeCommand.Parameters.AddWithValue("$newValue", value + 1L);
49+
writeCommand.ExecuteNonQuery();
50+
51+
// After the first write statment, both concurrent reads and writes are blocked
52+
// until the transaction completes
53+
54+
transaction.Commit();
55+
}
56+
#endregion
57+
58+
// Clean up
59+
connection.Close();
60+
File.Delete("DeferredTransactionSample.db");
61+
}
62+
}
63+
}

samples/snippets/standard/data/sqlite/Microsoft.Data.Sqlite.sln

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DapperSample", "DapperSampl
4343
EndProject
4444
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SqliteProviderSample", "SqliteProviderSample\SqliteProviderSample.csproj", "{E52BF2F4-6941-493F-8022-CD783889C1E2}"
4545
EndProject
46+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DeferredTransactionSample", "DeferredTransactionSample\DeferredTransactionSample.csproj", "{EC322E34-5012-43EE-B2D2-9F57A5F17289}"
47+
EndProject
4648
Global
4749
GlobalSection(SolutionConfigurationPlatforms) = preSolution
4850
Debug|Any CPU = Debug|Any CPU
@@ -129,6 +131,10 @@ Global
129131
{E52BF2F4-6941-493F-8022-CD783889C1E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
130132
{E52BF2F4-6941-493F-8022-CD783889C1E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
131133
{E52BF2F4-6941-493F-8022-CD783889C1E2}.Release|Any CPU.Build.0 = Release|Any CPU
134+
{EC322E34-5012-43EE-B2D2-9F57A5F17289}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
135+
{EC322E34-5012-43EE-B2D2-9F57A5F17289}.Debug|Any CPU.Build.0 = Debug|Any CPU
136+
{EC322E34-5012-43EE-B2D2-9F57A5F17289}.Release|Any CPU.ActiveCfg = Release|Any CPU
137+
{EC322E34-5012-43EE-B2D2-9F57A5F17289}.Release|Any CPU.Build.0 = Release|Any CPU
132138
EndGlobalSection
133139
GlobalSection(SolutionProperties) = preSolution
134140
HideSolutionNode = FALSE

0 commit comments

Comments
 (0)