From 17009083724c8617dcafb7afbd2809b532e55dd3 Mon Sep 17 00:00:00 2001 From: Brice Lambson Date: Fri, 14 Feb 2020 15:12:48 -0800 Subject: [PATCH] SQLite: Make SqliteDbContextOptionsBuilder.CommandTimeout() also set SqliteConnection.DefaultTimeout Fixes #18607 --- .../Internal/SqliteRelationalConnection.cs | 34 +++++++++----- .../Storage/SqliteRelationalConnectionTest.cs | 44 +++++++++++++++++++ 2 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 test/EFCore.Sqlite.Tests/Storage/SqliteRelationalConnectionTest.cs diff --git a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs index e53affbbaa1..4e3fd8c7048 100644 --- a/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs +++ b/src/EFCore.Sqlite.Core/Storage/Internal/SqliteRelationalConnection.cs @@ -31,6 +31,7 @@ public class SqliteRelationalConnection : RelationalConnection, ISqliteRelationa { private readonly IRawSqlCommandBuilder _rawSqlCommandBuilder; private readonly bool _loadSpatialite; + private readonly int? _commandTimeout; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -51,14 +52,13 @@ public SqliteRelationalConnection( if (optionsExtension != null) { _loadSpatialite = optionsExtension.LoadSpatialite; - if (_loadSpatialite) + + var relationalOptions = RelationalOptionsExtension.Extract(dependencies.ContextOptions); + _commandTimeout = relationalOptions.CommandTimeout; + + if (relationalOptions.Connection != null) { - var relationalOptions = RelationalOptionsExtension.Extract(dependencies.ContextOptions); - if (relationalOptions.Connection != null) - { - // TODO: Provide a better hook to do this for both external connections and ones created by EF - SpatialiteLoader.Load(relationalOptions.Connection); - } + InitializeDbConnection(relationalOptions.Connection); } } } @@ -72,11 +72,7 @@ public SqliteRelationalConnection( protected override DbConnection CreateDbConnection() { var connection = new SqliteConnection(GetCheckedConnectionString()); - - if (_loadSpatialite) - { - SpatialiteLoader.Load(connection); - } + InitializeDbConnection(connection); return connection; } @@ -95,5 +91,19 @@ public virtual ISqliteRelationalConnection CreateReadOnlyConnection() return new SqliteRelationalConnection(Dependencies.With(contextOptions), _rawSqlCommandBuilder); } + + private void InitializeDbConnection(DbConnection connection) + { + if (_loadSpatialite) + { + SpatialiteLoader.Load(connection); + } + + if (connection is SqliteConnection sqliteConnection + && _commandTimeout.HasValue) + { + sqliteConnection.DefaultTimeout = _commandTimeout.Value; + } + } } } diff --git a/test/EFCore.Sqlite.Tests/Storage/SqliteRelationalConnectionTest.cs b/test/EFCore.Sqlite.Tests/Storage/SqliteRelationalConnectionTest.cs new file mode 100644 index 00000000000..404597f2bea --- /dev/null +++ b/test/EFCore.Sqlite.Tests/Storage/SqliteRelationalConnectionTest.cs @@ -0,0 +1,44 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore.TestUtilities; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.EntityFrameworkCore.Storage +{ + public class SqliteRelationalConnectionTest + { + [Fact] + public void Sets_DefaultTimeout_when_connectionString() + { + var services = SqliteTestHelpers.Instance.CreateContextServices( + new DbContextOptionsBuilder() + .UseSqlite("Data Source=:memory:", x => x.CommandTimeout(42)) + .Options); + + var connection = (SqliteConnection)services.GetRequiredService().DbConnection; + + Assert.Equal(42, connection.DefaultTimeout); + } + + [Fact] + public void Sets_DefaultTimeout_when_connection() + { + var originalConnection = new SqliteConnection("Data Source=:memory:") + { + DefaultTimeout = 21 + }; + var services = SqliteTestHelpers.Instance.CreateContextServices( + new DbContextOptionsBuilder() + .UseSqlite(originalConnection, x => x.CommandTimeout(42)) + .Options); + + var connection = (SqliteConnection)services.GetRequiredService().DbConnection; + + Assert.Same(originalConnection, connection); + Assert.Equal(42, originalConnection.DefaultTimeout); + } + } +}