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: 2 additions & 2 deletions pages/directory-and-name-resolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public Task<SqlDatabase> Build(
string? databaseSuffix = null,
[CallerMemberName] string memberName = "")
```
<sup><a href='/src/LocalDb/SqlInstance.cs#L120-L142' title='Snippet source file'>snippet source</a> | <a href='#snippet-conventionbuildsignature' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/LocalDb/SqlInstance.cs#L132-L154' title='Snippet source file'>snippet source</a> | <a href='#snippet-conventionbuildsignature' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

With these parameters the database name is the derived as follows:
Expand Down Expand Up @@ -150,7 +150,7 @@ If full control over the database name is required, there is an overload that ta
/// </summary>
public async Task<SqlDatabase> Build(string dbName)
```
<sup><a href='/src/LocalDb/SqlInstance.cs#L157-L164' title='Snippet source file'>snippet source</a> | <a href='#snippet-explicitbuildsignature' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/LocalDb/SqlInstance.cs#L169-L176' title='Snippet source file'>snippet source</a> | <a href='#snippet-explicitbuildsignature' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->

Which can be used as follows:
Expand Down
1 change: 1 addition & 0 deletions src/EfClassicLocalDb/EfClassicLocalDb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<Compile Include="..\LocalDb\LocalDbInstanceInfo.cs" />
<Compile Include="..\LocalDb\LocalDbApi.cs" />
<Compile Include="..\LocalDb\MethodTimeLogger.cs" />
<Compile Include="..\LocalDb\ShutdownMode.cs" />
<Compile Include="..\LocalDb\SqlExtensions.cs" />
<Compile Include="..\LocalDb\Wrapper.cs" />
<Compile Include="..\LocalDb\State.cs" />
Expand Down
18 changes: 17 additions & 1 deletion src/EfClassicLocalDb/SqlInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,23 @@ static DateTime GetTimestamp(DateTime? timestamp, Delegate? buildTemplate)
return Timestamp.LastModified<TDbContext>();
}

public void Cleanup() => Wrapper.DeleteInstance();
public void Cleanup()
{
Guard.AgainstBadOS();
Wrapper.DeleteInstance();
}

public void Cleanup(ShutdownMode shutdownMode)
{
Guard.AgainstBadOS();
Wrapper.DeleteInstance(shutdownMode);
}

public void Cleanup(ShutdownMode shutdownMode, TimeSpan timeout)
{
Guard.AgainstBadOS();
Wrapper.DeleteInstance(shutdownMode, timeout);
}

Task<string> BuildDatabase(string dbName) => Wrapper.CreateDatabaseFromTemplate(dbName);

Expand Down
1 change: 1 addition & 0 deletions src/EfLocalDb/EfLocalDb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
<Compile Include="..\LocalDb\LocalDbInstanceInfo.cs" />
<Compile Include="..\LocalDb\LocalDbApi.cs" />
<Compile Include="..\LocalDb\MethodTimeLogger.cs" />
<Compile Include="..\LocalDb\ShutdownMode.cs" />
<Compile Include="..\LocalDb\SqlExtensions.cs" />
<Compile Include="..\LocalDb\Wrapper.cs" />
<Compile Include="..\LocalDb\State.cs" />
Expand Down
21 changes: 18 additions & 3 deletions src/LocalDb/LocalDbApi.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
using System.ComponentModel;
using System.Runtime.InteropServices;

#if EF
using EfLocalDb;
#else
using LocalDb;
#endif

static class LocalDbApi
{
static IntPtr api;
Expand Down Expand Up @@ -125,9 +131,14 @@ public static LocalDbInstanceInfo GetInstance(string instanceName)

public static void DeleteInstance(string instanceName) => deleteInstance(instanceName, 0);

public static void StopAndDelete(string instanceName)
private static readonly TimeSpan DefaultShutdownTimeout = TimeSpan.FromSeconds(10);

public static void StopAndDelete(string instanceName, ShutdownMode shutdownMode = ShutdownMode.KillProcess) =>
StopAndDelete(instanceName, shutdownMode, DefaultShutdownTimeout);

public static void StopAndDelete(string instanceName, ShutdownMode shutdownMode, TimeSpan timeout)
{
StopInstance(instanceName);
StopInstance(instanceName, shutdownMode, timeout);
DeleteInstance(instanceName);
}

Expand Down Expand Up @@ -160,5 +171,9 @@ public static void StartInstance(string instanceName)
startInstance(instanceName, 0, connection, ref size);
}

public static void StopInstance(string instanceName) => stopInstance(instanceName, 0, 10000);
public static void StopInstance(string instanceName, ShutdownMode shutdownMode = ShutdownMode.UseSqlShutdown) =>
StopInstance(instanceName, shutdownMode, DefaultShutdownTimeout);

public static void StopInstance(string instanceName, ShutdownMode shutdownMode, TimeSpan timeout) =>
stopInstance(instanceName, (int)shutdownMode, (int)timeout.TotalMilliseconds);
}
32 changes: 32 additions & 0 deletions src/LocalDb/ShutdownMode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#if EF
namespace EfLocalDb;
#else
namespace LocalDb;
#endif

/// <summary>
/// Provides options for how to shut down the instance.
/// </summary>
/// <remarks>
/// See https://docs.microsoft.com/sql/relational-databases/express-localdb-instance-apis/localdbstopinstance-function
/// </remarks>
public enum ShutdownMode
{
/// <summary>
/// Shutdown cleanly, using the <c>SHUTDOWN</c> T-SQL command.
/// See https://docs.microsoft.com/sql/t-sql/language-elements/shutdown-transact-sql
/// </summary>
UseSqlShutdown = 0,

/// <summary>
/// Shutdown immediately, by asking the operating system to kill the process hosting the instance.
/// The database may be corrupted by this approach, so only use when you intend to delete the instance.
/// </summary>
KillProcess = 1,

/// <summary>
/// Shutdown using the <c>SHUTDOWN WITH NOWAIT</c> T-SQL command, which does not perform checkpoints in the database.
/// See https://docs.microsoft.com/sql/t-sql/language-elements/shutdown-transact-sql
/// </summary>
UseSqlShutdownWithNoWait = 2
}
12 changes: 12 additions & 0 deletions src/LocalDb/SqlInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,18 @@ public void Cleanup()
Wrapper.DeleteInstance();
}

public void Cleanup(ShutdownMode shutdownMode)
{
Guard.AgainstBadOS();
Wrapper.DeleteInstance(shutdownMode);
}

public void Cleanup(ShutdownMode shutdownMode, TimeSpan timeout)
{
Guard.AgainstBadOS();
Wrapper.DeleteInstance(shutdownMode, timeout);
}

Task<string> BuildContext(string dbName) => Wrapper.CreateDatabaseFromTemplate(dbName);

#region ConventionBuildSignature
Expand Down
11 changes: 9 additions & 2 deletions src/LocalDb/Wrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -261,9 +261,16 @@ async Task Rebuild(DateTime timestamp, Func<DbConnection, Task> buildTemplate, D
}

[Time]
public void DeleteInstance()
public void DeleteInstance(ShutdownMode shutdownMode = ShutdownMode.KillProcess)
{
LocalDbApi.StopAndDelete(instance);
LocalDbApi.StopAndDelete(instance, shutdownMode);
System.IO.Directory.Delete(Directory, true);
}

[Time]
public void DeleteInstance(ShutdownMode shutdownMode, TimeSpan timeout)
{
LocalDbApi.StopAndDelete(instance, shutdownMode, timeout);
System.IO.Directory.Delete(Directory, true);
}

Expand Down