From db73e8f875079cbbe03c8a6417c6dce045c42e90 Mon Sep 17 00:00:00 2001 From: catcherwong Date: Sat, 21 Nov 2020 10:29:24 +0800 Subject: [PATCH] improve sqlite concurrency problem (#260) --- .../Configurations/SQLiteDatabaseProvider.cs | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/EasyCaching.SQLite/Configurations/SQLiteDatabaseProvider.cs b/src/EasyCaching.SQLite/Configurations/SQLiteDatabaseProvider.cs index b5237fe0..b3d19e24 100644 --- a/src/EasyCaching.SQLite/Configurations/SQLiteDatabaseProvider.cs +++ b/src/EasyCaching.SQLite/Configurations/SQLiteDatabaseProvider.cs @@ -2,7 +2,10 @@ { using EasyCaching.Core; using Microsoft.Data.Sqlite; - using Microsoft.Extensions.Options; + using System.Collections.Concurrent; + using System.Data; + using System.Threading; + using System.Threading.Tasks; /// /// SQLite database provider. @@ -16,16 +19,27 @@ public class SQLiteDatabaseProvider : ISQLiteDatabaseProvider public SQLiteDatabaseProvider(string name , SQLiteOptions options) { - this._name = name; - this._options = options.DBConfig; + _name = name; + _options = options.DBConfig; + _builder = new SqliteConnectionStringBuilder + { + DataSource = _options.DataSource, + Mode = _options.OpenMode, + Cache = _options.CacheMode + }; + + _conns = new ConcurrentDictionary(); } + private static ConcurrentDictionary _conns; + /// - /// The conn. + /// The builder /// - private static SqliteConnection _conn; + private static SqliteConnectionStringBuilder _builder; private readonly string _name = EasyCachingConstValue.DefaultSQLiteName; + public string DBProviderName => _name; /// @@ -34,19 +48,25 @@ public SQLiteDatabaseProvider(string name , SQLiteOptions options) /// The connection. public SqliteConnection GetConnection() { - if(_conn == null) + var threadId = Thread.CurrentThread.ManagedThreadId; + var con = _conns.GetOrAdd(threadId, CreateNewConnection()); + + Task.Run(async () => { - SqliteConnectionStringBuilder builder = new SqliteConnectionStringBuilder() + await Task.Delay(5000).ConfigureAwait(false); + _conns.TryRemove(threadId, out var removingConn); + if (removingConn?.State == ConnectionState.Closed) { - DataSource = _options.DataSource, - Mode = _options.OpenMode, - Cache = _options.CacheMode - }; + removingConn.Dispose(); + } + }); - _conn = new SqliteConnection(builder.ToString()); + return con; + } - } - return _conn; + private SqliteConnection CreateNewConnection() + { + return new SqliteConnection(_builder.ToString()); } } }