Sqlite атомных операций - PullRequest
       5

Sqlite атомных операций

0 голосов
/ 17 октября 2019

Я запускаю 5 приложений, использующих одну и ту же базу данных sqlite (каждое приложение - это отдельный процесс). К сожалению, такие операции, как GetEmptyPort, должны быть атомарными, чтобы предотвратить возврат одинаковых значений. Прямо сейчас я добиваюсь этого, используя систему Mutex, но мне не нравится это решение. Есть ли какое-либо встроенное решение для этого в чистом виде sqlite?

Это мой код:

private static Mutex DB_MUTEX = new Mutex(false, "FOO_DB_MUTEX");

private T OnMutexWork<T>(Func<T> func)
{
    try
    {
        DB_MUTEX.WaitOne();
        return func.Invoke();
    }
    catch (Exception ex)
    {
        throw;
    }
    finally
    {
        DB_MUTEX.ReleaseMutex();
    }
}

private SQLiteConnection GetConnection()
{
    return new SQLiteConnection(databasePath);
}

private int GetEmptyPort(int min, int max)
{
    return OnMutexWork<int>(() =>
    {
        using (var conn = GetConnection())
        {
            var allPorts = conn.Table<Port>()
                    .ToList();

            for (int i = min; i <= max; i++)
            {
                if (!allPorts.Any(x => x.Value == i))
                {
                    var item = new Port() { Value = i};
                    conn.Insert(item);
                    return i;
                }
            }

            throw new Exception("Couldn't find empty port");
        }
    });
}

Я попробовал то, что @Shawn предложил:

private int GetEmptyPort(int min, int max)
{
    using (var conn = GetConnection())
    {
        conn.RunInTransaction(() =>
        {
            var allPorts = conn.Table<Port>()
                .ToList();

            for (int i = min; i <= max; i++)
            {
                if (!allPorts.Any(x => x.Value == i))
                {
                    var item = new Port() { Value = i};
                    conn.Insert(item);
                    return i;
                }
            }
        });

        throw new Exception("Couldn't find empty port");
    }
}

Но я получаю SQLite.SQLiteException: 'Busy' ошибку при доступе к базе данных из разных соединений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...