diff --git a/pages/raw-usage.md b/pages/raw-usage.md
index 90dae8f0..b5bb6ec3 100644
--- a/pages/raw-usage.md
+++ b/pages/raw-usage.md
@@ -271,7 +271,7 @@ public async Task SharedDatabase()
AreEqual(0, data.Count);
}
```
-snippet source | anchor
+snippet source | anchor
Pass `useTransaction: true` to get an auto-rolling-back transaction, allowing writes without affecting other tests.
@@ -307,5 +307,5 @@ public async Task SharedDatabase_WithTransaction()
AreEqual(0, data.Count);
}
```
-snippet source | anchor
+snippet source | anchor
diff --git a/pages/template-database-size.md b/pages/template-database-size.md
index bc73856e..eb2534b9 100644
--- a/pages/template-database-size.md
+++ b/pages/template-database-size.md
@@ -21,7 +21,7 @@ To have a smaller file size [DBCC SHRINKFILE](https://docs.microsoft.com/en-us/s
use model;
dbcc shrinkfile(modeldev, {size})
```
-snippet source | anchor
+snippet source | anchor
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 8fc2ee3a..8a97ed8d 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -2,7 +2,7 @@
CS1591;CA1416;CS8632;NU1608;NU1109
- 24.1.0
+ 24.1.1
preview
1.0.0
false
diff --git a/src/LocalDb.Tests/Tests.cs b/src/LocalDb.Tests/Tests.cs
index db5644cd..774b7229 100644
--- a/src/LocalDb.Tests/Tests.cs
+++ b/src/LocalDb.Tests/Tests.cs
@@ -78,6 +78,40 @@ public async Task Callback()
True(callbackCalled);
}
+ [Test]
+ public async Task BuildTemplateLeavesConnectionOpen()
+ {
+ // Mimics a buildTemplate callback (e.g. an SMO ServerConnection) that opens its
+ // own connection to the template and leaves it open. Setting read_committed_snapshot
+ // requires exclusive access, so the rebuild must evict that lingering session
+ // ("with rollback immediate"); otherwise the alter blocks until the command timeout.
+ SqlConnection? leaked = null;
+ using var instance = new SqlInstance(
+ "Tests_BuildTemplateLeavesConnectionOpen",
+ async connection =>
+ {
+ await TestDbBuilder.CreateTable(connection);
+ leaked = new(connection.ConnectionString);
+ await leaked.OpenAsync();
+ });
+
+ try
+ {
+ await using var database = await instance.Build();
+ var data = await TestDbBuilder.AddData(database.Connection);
+ Contains(data, await TestDbBuilder.GetData(database.Connection));
+ }
+ finally
+ {
+ if (leaked != null)
+ {
+ await leaked.DisposeAsync();
+ }
+
+ instance.Cleanup();
+ }
+ }
+
//[Test]
//public async Task SuppliedTemplate()
//{
diff --git a/src/LocalDb/SqlBuilder.cs b/src/LocalDb/SqlBuilder.cs
index 4b78b40c..041fdd8a 100644
--- a/src/LocalDb/SqlBuilder.cs
+++ b/src/LocalDb/SqlBuilder.cs
@@ -58,10 +58,14 @@ create database [template] on
// shared locks, preventing S/X-lock deadlocks
// between parallel [SharedDbWithTransaction] tests
// against the same shared database.
+ // read_committed_snapshot requires exclusive access to the database, so it uses
+ // "with rollback immediate" to evict any sessions a buildTemplate/callback left
+ // open (e.g. an SMO ServerConnection). Without it the statement blocks on those
+ // sessions until the command timeout expires.
public static string TemplateSettingsCommand =
"""
alter database [template] set auto_update_statistics off;
- alter database [template] set read_committed_snapshot on;
+ alter database [template] set read_committed_snapshot on with rollback immediate;
""";
public static string DetachAndShrinkTemplateCommand =