我有一个"Vulcan.edb"
从正在使用的应用程序复制的 ESE 数据库 ( )。自然,这意味着数据库处于“脏关机”状态。幸运的是,我确实有数据库的日志文件("V01.log"
),根据我能找到的每个 类似 问题,我应该能够附加数据库并让引擎恢复它。这是我用来附加数据库的代码,使用托管 ESE API(非托管 C++ 端口应该是微不足道的):
public void ReadFromDatabase(string fileName, string logFileBaseName)
{
string databaseDirectory = Path.GetDirectoryName(fileName);
int pageSize;
Api.JetGetDatabaseFileInfo(fileName, out pageSize, JET_DbInfo.PageSize);
Api.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.DatabasePageSize, pageSize, null);
Api.JetSetSystemParameter(JET_INSTANCE.Nil, JET_SESID.Nil, JET_param.Recovery, 0, "Off");
JET_INSTANCE jetInstance;
string jetInstanceName = Guid.NewGuid().ToString("N");
Api.JetCreateInstance(out jetInstance, jetInstanceName);
Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, JET_param.BaseName, 0, logFileBaseName);
Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, JET_param.LogFilePath, 0, databaseDirectory);
Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, JET_param.TempPath, 0, databaseDirectory);
Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, JET_param.SystemPath, 0, databaseDirectory);
Api.JetSetSystemParameter(jetInstance, JET_SESID.Nil, Microsoft.Isam.Esent.Interop.Server2003.Server2003Param.AlternateDatabaseRecoveryPath, 0, databaseDirectory);
try
{
Api.JetInit(ref jetInstance);
JET_SESID sessionId;
Api.JetBeginSession(jetInstance, out sessionId, "admin", "");
try
{
Api.JetAttachDatabase(sessionId, fileName, AttachDatabaseGrbit.ReadOnly);
JET_DBID databaseId;
Api.JetOpenDatabase(sessionId, fileName, "", out databaseId, OpenDatabaseGrbit.ReadOnly);
// Do other stuff here...
Api.JetCloseDatabase(sessionId, databaseId, CloseDatabaseGrbit.None);
}
finally
{
Api.JetEndSession(sessionId, EndSessionGrbit.None);
}
}
finally
{
Api.JetTerm(jetInstance);
}
}
实际上,如果我将数据库文件和日志文件都复制到<directory of database>
并运行
edbntutl.exe /r V01 /l <directory of database> /s <directory of database> /d <directory of database>
,则数据库在我的代码中变得可用和可附加。但是,如果我不采取手动恢复数据库的步骤,我的代码调用失败JetAttachDatabase
,错误为JET_errDatabaseDirtyShutdown
.
那么为什么我的代码不能自动恢复数据库呢?要么edbntutl
正在做一些未记录的事情,要么我在会话配置中遗漏了一些东西以允许引擎恢复数据库。虽然前者不是不可能的,但如果是这样的话,那将是非常不幸的,而且我倾向于相信我只是错过了一些东西。
注意:如果没有证据表明实用程序正在执行公共 API 中不可用的操作,则不会接受相当于“在运行代码之前运行 esentutil”的答案。