diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
index 1337127eac8..a456763751c 100644
--- a/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
+++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnection.cs
@@ -130,7 +130,7 @@ public override string DataSource
/// Database Errors
public virtual int DefaultTimeout
{
- get => _defaultTimeout ?? 30;
+ get => _defaultTimeout ?? ConnectionOptions.DefaultTimeout;
set => _defaultTimeout = value;
}
diff --git a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionStringBuilder.cs b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionStringBuilder.cs
index e19252c2365..c54d8597bb5 100644
--- a/src/Microsoft.Data.Sqlite.Core/SqliteConnectionStringBuilder.cs
+++ b/src/Microsoft.Data.Sqlite.Core/SqliteConnectionStringBuilder.cs
@@ -28,6 +28,8 @@ public class SqliteConnectionStringBuilder : DbConnectionStringBuilder
private const string PasswordKeyword = "Password";
private const string ForeignKeysKeyword = "Foreign Keys";
private const string RecursiveTriggersKeyword = "Recursive Triggers";
+ private const string DefaultTimeoutKeyword = "Default Timeout";
+ private const string CommandTimeoutKeyword = "Command Timeout";
private enum Keywords
{
@@ -36,7 +38,8 @@ private enum Keywords
Cache,
Password,
ForeignKeys,
- RecursiveTriggers
+ RecursiveTriggers,
+ DefaultTimeout
}
private static readonly IReadOnlyList _validKeywords;
@@ -48,19 +51,21 @@ private enum Keywords
private string _password = string.Empty;
private bool? _foreignKeys;
private bool _recursiveTriggers;
+ private int _defaultTimeout = 30;
static SqliteConnectionStringBuilder()
{
- var validKeywords = new string[6];
+ var validKeywords = new string[7];
validKeywords[(int)Keywords.DataSource] = DataSourceKeyword;
validKeywords[(int)Keywords.Mode] = ModeKeyword;
validKeywords[(int)Keywords.Cache] = CacheKeyword;
validKeywords[(int)Keywords.Password] = PasswordKeyword;
validKeywords[(int)Keywords.ForeignKeys] = ForeignKeysKeyword;
validKeywords[(int)Keywords.RecursiveTriggers] = RecursiveTriggersKeyword;
+ validKeywords[(int)Keywords.DefaultTimeout] = DefaultTimeoutKeyword;
_validKeywords = validKeywords;
- _keywords = new Dictionary(8, StringComparer.OrdinalIgnoreCase)
+ _keywords = new Dictionary(10, StringComparer.OrdinalIgnoreCase)
{
[DataSourceKeyword] = Keywords.DataSource,
[ModeKeyword] = Keywords.Mode,
@@ -68,10 +73,12 @@ static SqliteConnectionStringBuilder()
[PasswordKeyword] = Keywords.Password,
[ForeignKeysKeyword] = Keywords.ForeignKeys,
[RecursiveTriggersKeyword] = Keywords.RecursiveTriggers,
+ [DefaultTimeoutKeyword] = Keywords.DefaultTimeout,
// aliases
[FilenameKeyword] = Keywords.DataSource,
- [DataSourceNoSpaceKeyword] = Keywords.DataSource
+ [DataSourceNoSpaceKeyword] = Keywords.DataSource,
+ [CommandTimeoutKeyword] = Keywords.DefaultTimeout
};
}
@@ -185,6 +192,16 @@ public bool RecursiveTriggers
set => base[RecursiveTriggersKeyword] = _recursiveTriggers = value;
}
+ ///
+ /// Gets or sets the default value.
+ ///
+ /// The default value.
+ public int DefaultTimeout
+ {
+ get => _defaultTimeout;
+ set => base[DefaultTimeoutKeyword] = _defaultTimeout = value;
+ }
+
///
/// Gets or sets the value associated with the specified key.
///
@@ -230,6 +247,10 @@ public override object? this[string keyword]
RecursiveTriggers = Convert.ToBoolean(value, CultureInfo.InvariantCulture);
return;
+ case Keywords.DefaultTimeout:
+ DefaultTimeout = Convert.ToInt32(value);
+ return;
+
default:
Debug.Assert(false, "Unexpected keyword: " + keyword);
return;
@@ -372,6 +393,9 @@ public override bool TryGetValue(string keyword, out object? value)
case Keywords.RecursiveTriggers:
return RecursiveTriggers;
+ case Keywords.DefaultTimeout:
+ return DefaultTimeout;
+
default:
Debug.Assert(false, "Unexpected keyword: " + index);
return null;
@@ -411,6 +435,10 @@ private void Reset(Keywords index)
_recursiveTriggers = false;
return;
+ case Keywords.DefaultTimeout:
+ _defaultTimeout = 30;
+ return;
+
default:
Debug.Assert(false, "Unexpected keyword: " + index);
return;
diff --git a/test/Microsoft.Data.Sqlite.Tests/SqliteCommandTest.cs b/test/Microsoft.Data.Sqlite.Tests/SqliteCommandTest.cs
index a403fdd4489..50f845304e5 100644
--- a/test/Microsoft.Data.Sqlite.Tests/SqliteCommandTest.cs
+++ b/test/Microsoft.Data.Sqlite.Tests/SqliteCommandTest.cs
@@ -20,7 +20,6 @@ public void Ctor_sets_values()
{
using (var connection = new SqliteConnection("Data Source=:memory:"))
{
- connection.DefaultTimeout = 1;
connection.Open();
using (var transaction = connection.BeginTransaction())
@@ -29,7 +28,6 @@ public void Ctor_sets_values()
Assert.Equal("SELECT 1;", command.CommandText);
Assert.Same(connection, command.Connection);
- Assert.Equal(1, command.CommandTimeout);
Assert.Same(transaction, command.Transaction);
}
}
@@ -75,6 +73,54 @@ public void CommandText_throws_when_set_when_open_reader()
}
}
+ [Fact]
+ public void CommandTimeout_works()
+ {
+ var command = new SqliteCommand
+ {
+ Connection = new SqliteConnection("Command Timeout=1")
+ {
+ DefaultTimeout = 2
+ },
+ CommandTimeout = 3
+ };
+
+ Assert.Equal(3, command.CommandTimeout);
+ }
+
+ [Fact]
+ public void CommandTimeout_defaults_to_connection()
+ {
+ var command = new SqliteCommand
+ {
+ Connection = new SqliteConnection("Default Timeout=1")
+ {
+ DefaultTimeout = 2
+ }
+ };
+
+ Assert.Equal(2, command.CommandTimeout);
+ }
+
+ [Fact]
+ public void CommandTimeout_defaults_to_connection_string()
+ {
+ var command = new SqliteCommand
+ {
+ Connection = new SqliteConnection("Default Timeout=1")
+ };
+
+ Assert.Equal(1, command.CommandTimeout);
+ }
+
+ [Fact]
+ public void CommandTimeout_defaults_to_30()
+ {
+ var command = new SqliteCommand();
+
+ Assert.Equal(30, command.CommandTimeout);
+ }
+
[Fact]
public void Connection_can_be_unset()
{
diff --git a/test/Microsoft.Data.Sqlite.Tests/SqliteConnectionStringBuilderTest.cs b/test/Microsoft.Data.Sqlite.Tests/SqliteConnectionStringBuilderTest.cs
index b52bfbb4bdd..6c5feffbfb0 100644
--- a/test/Microsoft.Data.Sqlite.Tests/SqliteConnectionStringBuilderTest.cs
+++ b/test/Microsoft.Data.Sqlite.Tests/SqliteConnectionStringBuilderTest.cs
@@ -10,10 +10,13 @@ namespace Microsoft.Data.Sqlite
{
public class SqliteConnectionStringBuilderTest
{
- [Fact]
- public void Ctor_parses_options()
+ [Theory]
+ [InlineData("Data Source")]
+ [InlineData("Filename")]
+ [InlineData("DataSource")]
+ public void Ctor_parses_DataSource(string keyword)
{
- var builder = new SqliteConnectionStringBuilder("Data Source=test.db");
+ var builder = new SqliteConnectionStringBuilder($"{keyword}=test.db");
Assert.Equal("test.db", builder.DataSource);
}
@@ -33,6 +36,40 @@ public void Ctor_parses_mode()
Assert.Equal(SqliteOpenMode.Memory, builder.Mode);
}
+ [Fact]
+ public void Ctor_parses_Password()
+ {
+ var builder = new SqliteConnectionStringBuilder("Password=key");
+
+ Assert.Equal("key", builder.Password);
+ }
+
+ [Fact]
+ public void Ctor_parses_ForeignKeys()
+ {
+ var builder = new SqliteConnectionStringBuilder("Foreign Keys=True");
+
+ Assert.True(builder.ForeignKeys);
+ }
+
+ [Fact]
+ public void Ctor_parses_RecursiveTriggers()
+ {
+ var builder = new SqliteConnectionStringBuilder("Recursive Triggers=True");
+
+ Assert.True(builder.RecursiveTriggers);
+ }
+
+ [Theory]
+ [InlineData("Default Timeout")]
+ [InlineData("Command Timeout")]
+ public void Ctor_parses_DefaultTimeout(string keyword)
+ {
+ var builder = new SqliteConnectionStringBuilder($"{keyword}=1");
+
+ Assert.Equal(1, builder.DefaultTimeout);
+ }
+
[Fact]
public void ConnectionString_defaults_to_empty()
{
@@ -111,19 +148,26 @@ public void Password_defaults_to_empty()
Assert.Empty(new SqliteConnectionStringBuilder().Password);
}
+ [Fact]
+ public void DefaultTimeout_defaults_to_30()
+ {
+ Assert.Equal(30, new SqliteConnectionStringBuilder().DefaultTimeout);
+ }
+
[Fact]
public void Keys_works()
{
var keys = (ICollection)new SqliteConnectionStringBuilder().Keys;
Assert.True(keys.IsReadOnly);
- Assert.Equal(6, keys.Count);
+ Assert.Equal(7, keys.Count);
Assert.Contains("Data Source", keys);
Assert.Contains("Mode", keys);
Assert.Contains("Cache", keys);
Assert.Contains("Password", keys);
Assert.Contains("Foreign Keys", keys);
Assert.Contains("Recursive Triggers", keys);
+ Assert.Contains("Default Timeout", keys);
}
[Fact]
@@ -132,7 +176,7 @@ public void Values_works()
var values = (ICollection