Skip to content

LiteDb and SqliteDb problems #260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
haiduong87 opened this issue Nov 12, 2020 · 7 comments
Closed

LiteDb and SqliteDb problems #260

haiduong87 opened this issue Nov 12, 2020 · 7 comments

Comments

@haiduong87
Copy link
Contributor

haiduong87 commented Nov 12, 2020

Description

I've encountered concurrency problem when using LiteDb or SqliteDb

Steps to Reproduce

  1. Use any of two mentions caches
  2. Deploy in IIS Web garden model (many workers)

Related code

insert short code snippets here

Expected behavior: [What you expected to happen]

Actual behavior: [What actually happened]

Specifications

  • Provider : Latest LiteDb or SqliteDb
  • Interceptor : AspectCore (version 0.2.0)
  • Serializer : not use
  • System : Windows 10 64bit, latest IIS

Problem with LiteDb

Problem with SqliteDb

`
public class SQLiteDatabaseProvider : ISQLiteDatabaseProvider
{
private static ConcurrentDictionary<int, SqliteConnection> _conns;

    /// <summary>
    ///     The builder
    /// </summary>
    private static SqliteConnectionStringBuilder _builder;
    /// <summary>
    ///     The conn.
    /// </summary>
    private static SqliteConnection _conn;

    /// <summary>
    ///     The options.
    /// </summary>
    private readonly SQLiteDBOptions _options;

    public SQLiteDatabaseProvider(string name, SQLiteOptions options)
    {
        DBProviderName = name;
        _options = options.DBConfig;
        _builder = new SqliteConnectionStringBuilder
        {
            DataSource = _options.DataSource,
            Mode = _options.OpenMode,
            Cache = _options.CacheMode
        };

        _conns = new ConcurrentDictionary<int, SqliteConnection>();
    }

    public string DBProviderName { get; } = EasyCachingConstValue.DefaultSQLiteName;

    /// <summary>
    ///     Gets the connection.
    /// </summary>
    /// <returns>The connection.</returns>
    public SqliteConnection GetConnection_Original()
    {
        if (_conn == null)
        {
            _conn = new SqliteConnection(_builder.ToString());
        }

        return _conn;
    }

    /// <summary>
    ///     Get or create the connection from pool (For thread safe)
    /// </summary>
    /// <returns></returns>
    public SqliteConnection GetConnection()
    {
        var threadId = Thread.CurrentThread.ManagedThreadId;
        var con = _conns.GetOrAdd(threadId, CreateNewConnection());
        Task.Run(async () =>
        {
            await Task.Delay(5000).ConfigureAwait(false);
            _conns.TryRemove(threadId, out var removingConn);
            if (removingConn?.State == ConnectionState.Closed)
            {
                removingConn.Dispose();
            }
        });
        return con;
    }

    private SqliteConnection CreateNewConnection()
    {
        return new SqliteConnection(_builder.ToString());
    }
}

/// <summary>
/// SQLiteCaching provider.
/// </summary>
public partial class DefaultSQLiteCachingProvider : EasyCachingAbstractProvider
{
    /// <summary>
    /// The cache.
    /// </summary>
    private ISQLiteDatabaseProvider _dbProvider;

    /// <summary>
    /// The options.
    /// </summary>
    private readonly SQLiteOptions _options;

    /// <summary>
    /// The logger.
    /// </summary>
    private readonly ILogger _logger;

    /// <summary>
    /// The cache.
    /// </summary>
    private SqliteConnection _cache => _dbProvider.GetConnection();
}    

`

@catcherwong
Copy link
Member

@haiduong87 Thanks for your interest in this project.

We will take a look ASAP.

@catcherwong
Copy link
Member

Based on your sqlite fixed code.

Some Unit tests do not pass yet.

image

@haiduong87
Copy link
Contributor Author

Hi,

I'm not sure the test is stable :(
Just download master branch and try.

image

Note:

  • I do several times
  • With and without the fix
  • Then delete the folder and try again with the original source (the captured picture is the original code)

@catcherwong
Copy link
Member

When running the unit tests in a single class, all the tests can pass, but running together with 4 classes will not pass.

@catcherwong
Copy link
Member

I have committed the code, and the unit tests of SQLite runs well in the CI environment.

It seems that there are some difference between using dotnet test and visual studio

A preview version was published for this issue.

BTW, PR is welcome, if you find out some problems, you can submit a PR to fix it. 😄

@haiduong87
Copy link
Contributor Author

Hi,

I'm trying to fix the provider #264

But it does not pass all tests

@haiduong87
Copy link
Contributor Author

Hi @catcherwong

I think I found the problem,

image

This static field is not good for "many providers" case.

And so the latest code has bug too.

I will make change and test again.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants