3

在 的文档中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:数据库文件已被另一个会话附加。

如何打开多个会话?

因此,现在与其太随意地连枷,不如寻求正确的方法。

如何使用可扩展存储引擎开始多个会话

奖金

我确实有些随意地连枷。如果呼叫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);

它实际上似乎恰好起作用。

...耶?

4

1 回答 1

3

What you did in your "flailing" was the correct way to access the database from multiple sessions.

JetAttachDatabase() opens the file and associates it with an instance. It only needs to be called once.

JetOpenDatabase() opens a handle to the database within the session and can be called on each session.

于 2016-05-19T19:42:39.293 回答