Как начать несколько сеансов с Extensible Storage Engine
В документации для JetBeginSession
, он отмечает, что сеанс является единицей гранулярности, которая определяет транзакцию, он определяет, где находится курсор в вашей текущей открытой таблице, он определяет текущий активный индекс. На одном сеансе ничего нельзя сделать. Но они отмечают:
Для повышения параллелизма и параллельного доступа к базе данных можно начать несколько сеансов.
Что я и хотел бы. Я хотел бы открыть второй сеанс для базы данных.
Фон
ESE несколько запутан в том, как вы это делаете:
JetCreateInstance(out instance, "UniqueInstanceName"); //Create a uniquely named instance of the ESE in our process
JetInit(instance); //initialize the instance
JetBeginSession(instance, out sessionID); //initialize a session on the instance
JetAttachDatabase(sessionID, filename); //attach a database file to our session
JetOpenDatabase(sessionID, filename, "", out databaseID, 0); //open the database file in our session
//...now we can open table, get data, etc
//E.g. JetOpenTable(sessionID, databaseID, "Customers", null, 0, JET_bitTableReadOnly, out tableID);
JetCloseDatabase(sessionID, databaseID);
JetDetachDatabase(sessionID, filename);
JetEndSession(sessionID, 0);
JetTerm(instance);
И это все работает.
Но как нам открыть еще одну сессию?
Документация ESE, хотя и редкая, намекает на возможность иметь несколько сеансов для одной и той же базы данных:
- Для повышения параллелизма и параллельного доступа к базе данных можно начать несколько сеансов.
JET_bitTableDenyRead
- Таблица не может быть открыта для чтения другим сеансом базы данных. (подразумевается, что иногда он может быть открыт для чтения другим сеансом)JET_bitTableDenyWrite
- Таблица не может быть открыта для доступа для записи другим сеансом базы данных. (подразумевается, что иногда он может быть открыт для доступа для записи другим сеансом)JetOpenDatabase
- Эта функция может вызываться несколько раз для одной и той же базы данных.JET_bitDbExclusive
- Позволяет только один сеанс присоединить базу данных. Обычно несколько сеансов могут открыть базу данных. (акцент мой)
Наивным подходом было бы начать еще одну сессию:
//Startup the instance
JetCreateInstance(out instance, "UniqueInstanceName");
JetInit(instance);
//Make first session
JetBeginSession(instance, out sessionID);
JetAttachDatabase(sessionID, filename);
JetOpenDatabase(sessionID, filename, "", out databaseID, 0);
//Startup second session
JetBeginSession(instance, out session2ID);
JetAttachDatabase(session2ID, filename);
JetOpenDatabase(session2ID, filename, "", out database2ID, 0);
//Teardown second session
JetCloseDatabase(session2ID, database2ID);
JetDetachDatabase(session2ID, filename); <----hangs
JetEndSession(session2ID, 0);
//Teardown first session
JetCloseDatabase(sessionID, databaseID);
JetDetachDatabase(sessionID, filename);
JetEndSession(sessionID, 0);
//Terminate instance
JetTerm(instance);
Кроме звонка JetDetachDatabase
во второй сессии висит.
- Проверка документации
JetDetachDatabase
не помогает - Проверка
JetAttachDatabase
мы сталкиваемся с чем-то тревожным.
Существует код ошибки, подразумевающий, что попытка присоединить базу данных, которая уже была присоединена к другому сеансу, является ошибкой:
JET_errDatabaseSharingViolation: файл базы данных уже был прикреплен другим сеансом.
Как открыть несколько сессий?
Так что теперь, вместо того, чтобы шататься слишком случайно, я попрошу правильный способ сделать это.
Как начать несколько сеансов с Extensible Storage Engine
бонус
Я колебался несколько случайно. Если звонок JetDetachDatabase
висит, давайте просто не называть это! Это полностью нарушает документированные правила:
JetOpenDatabase
говорит, что я должен позвонитьJetAttachDatabase
первыйJetAttachDatabase
говорит, что я должен позвонитьJetDetachDatabase
Но попробуем это:
//Startup the instance
JetCreateInstance(out instance, "UniqueInstanceName");
JetInit(instance);
//Make first session
JetBeginSession(instance, out sessionID);
JetAttachDatabase(sessionID, filename);
JetOpenDatabase(sessionID, filename, "", out databaseID, 0);
//Startup second session
JetBeginSession(instance, out session2ID);
JetOpenDatabase(session2ID, filename, "", out database2ID, 0);
//Teardown second session
JetCloseDatabase(session2ID, database2ID);
JetEndSession(session2ID, 0);
//Teardown first session
JetCloseDatabase(sessionID, databaseID);
JetDetachDatabase(sessionID, filename);
JetEndSession(sessionID, 0);
//Terminate instance
JetTerm(instance);
И на самом деле кажется, что это работает.
...ура?
1 ответ
То, что вы сделали в своем "колебании", было правильным способом доступа к базе данных из нескольких сеансов.
JetAttachDatabase()
открывает файл и связывает его с экземпляром. Это нужно вызвать только один раз.
JetOpenDatabase()
открывает дескриптор базы данных в рамках сеанса и может вызываться при каждом сеансе.