Страницы

Поиск по вопросам

воскресенье, 8 декабря 2019 г.

Как выполнить Сжатие и восстановление Access базы через Interop?

#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);

Комментариев нет:

Отправить комментарий