#c_sharp #net #com #ms_access #office_interop
Как выполнить Сжатие и восстановление Access базы через Interop?
Есть класс, который содержит метод:
public bool TryCompactAndRepair()
{
string pathToDb = app.CurrentDb().Name;
string pathToCompact = Path.Combine(Path.GetDirectoryName(pathToDb),
Path.GetFileNameWithoutExtension(pathToDb)) +
"_compact" + Path.GetExtension(pathToDb);
db.Close();
app.CloseCurrentDatabase();
// Marshal.ReleaseComObject(db);
GC.Collect();
if (app.CompactRepair(pathToDb, pathToCompact, true))
{
File.Delete(pathToDb);
File.Move(pathToCompact, pathToDb);
return true;
}
else
{
File.Delete(pathToCompact);
}
return false;
}
переменная app имеет тип Application.
Почему-то такой метод возвращает различные ошибки:
В текущем виде, что-то вроде "Object no longer set"
Если раскоментить Marshal.ReleaseComObject(db); ,то получаю ошибку, что доступ к
объекту не доступен.
Если вообще не делать Close, то вылетает ошибка, что нельзя сделать сжатие для текущей БД.
Подскажите, в чем косяк?
Ответы
Ответ 1
Вызов app.CurrentDb().Name создает управляемую обертку COM-объекта dao.Database, ссылка на которую нигде не сохраняется, так что ее никак нельзя впоследствии освободить, кроме как финализатором. Из-за этого программа держит базу даже после вызовов app.CloseCurrentDatabase() и Marshal.ReleaseComObject на втором экземпляре объекта. Вызов GC.Collect() не помогает, так как финализатор выполняется не сразу, а только через некоторое время. Чтобы нормально освободить базу, нужно избавиться от создания второго экземпляра объекта (так как он не нужен): dao.Database db = app.CurrentDb(); string pathToDb = db.Name; string pathToCompact = Path.Combine(Path.GetDirectoryName(pathToDb), Path.GetFileNameWithoutExtension(pathToDb)) + "_compact" + Path.GetExtension(pathToDb); app.CloseCurrentDatabase(); Marshal.ReleaseComObject(db); app.CompactRepair(pathToDb, pathToCompact, true);
Комментариев нет:
Отправить комментарий