Нарушение совместного доступа к файлам. SQL Server CE 3.5 с пакетом обновления 2 (SP2)

У меня возникла эта случайная проблема в моем приложении .NET CF, которое использует базу данных SQL Server CE 3.5 SP2.

Когда приложение CF запускается, оно выполняет обслуживание базы данных для проверки .SDF файла базы данных для проверки с использованием класса Engine SQL Server CE:

using (SqlCeEngine engine = new SqlCeEngine(Resources.SqlCeConnectionString))
{
   Log.Info("Starting database Verification.");

   if (!engine.Verify())
   {
      Log.Warn("Database failed verification.");
      engine.Repair(null, RepairOption.RecoverAllOrFail);
      Log.Info("Database successfully repaired.");
   }
   else
   {
      Log.Info("Database Verification successful.");
   }
}

Если приложение проверено правильно, я копирую .SDF в резервную папку:

if (File.Exists(Resources.DatabaseFileLocation))
{
   File.Delete(Resources.BackupDatabaseFileLocation);
   File.Copy(Resources.DatabaseFileLocation, Resources.BackupDatabaseFileLocation);
   Log.Info("Database backup complete.");
}
else
{
   Log.Info("Could not find Device Database.");
}

После завершения резервного копирования приложение запускается, и первое соединение, которое приложение пытается установить с .SDF, приводит к следующему исключению:

There is a file sharing violation. A different process might be using the file.

Вот информация о файле журнала:

2013-05-13 11:52:29,894 [INFO ] - Starting database Verification.
2013-05-13 11:52:33,832 [INFO ] - Database Verification successful.
2013-05-13 11:52:33,838 [INFO ] - Database backup starting.
2013-05-13 11:52:46,941 [INFO ] - Database backup complete.
2013-05-13 11:52:47,933 [ERROR] - There is a file sharing violation. A different process might be using the file. [ \Program Files\ApplicationName\DB.sdf ]
    at System.Data.SqlServerCe.SqlCeConnection.ProcessResults(Int32 hr)    at System.Data.SqlServerCe.SqlCeConnection.Open(Boolean silent)
    at System.Data.SqlServerCe.SqlCeConnection.Open()
    at CFApp.MainScreen.GetStartupData()
    at CFApp.MainScreen..ctor()
    at CFApp.Program.RunInReleaseMode() 
    at CFApp.Program.Main()

Я уже несколько недель исследую причины этой проблемы и ничего не могу найти. Будем очень признательны за любое руководство или помощь.

Исходя из моих усилий, я могу подтвердить эти вещи

  • Проблема возникает случайно. Процедура запуска выполняется правильно несколько раз, а затем случайным образом выдает эту ошибку
  • В настоящее время нет никаких других подключений к базе данных, учитывая, что приложение только что запускается.
  • Каждый раз, когда приложение открывает соединение, оно удаляет его сразу после завершения. Это делается с помощью using операторов. Открытое соединение не остается открытым в случае неожиданного выключения / перезапуска.
  • SqlCeEngine удаляется с помощью оператора using. Есть ли возможная задержка между удалением объекта и закрытием его соединения?
  • В настоящее время нет других запущенных процессов. Устройство заблокировано, чтобы разрешить выполнение только моего приложения. Диспетчер задач показывает только ActiveSync и мое приложение. Время от времени устройство связывается с другим настольным приложением, используя OpenNETCF.Desktop.Communication библиотеку RAPI через USB. Для правильной работы необходимо включить Active Sync. Настольный компьютер, с которым он взаимодействует, - это Win XP.
  • На некоторых других форумах я видел, что ActiveSync может блокировать файл, что может вызвать проблему. В разделе ActiveSync устройства ничего не выбрано для синхронизации с рабочим столом. Флажок "Файлы" снят. Если у кого-то еще есть предложения о том, как я могу исключить этот файл из ActiveSync, это также будет очень полезно.

  • ОБНОВЛЕНИЕ. Я использовал dotPeek, чтобы изучить метод SqlCeEngine Dispose. Я думаю, что здесь все в порядке и мое соединение должно правильно утилизироваться?

    private void Dispose(bool disposing)
    {
      if (!disposing)
        return;
      this.connStr = (string) null;
      this.connTokens = (Hashtable) null;
      NativeMethods.DllRelease();
      this.isDisposed = true;
    }
    
  • ОБНОВЛЕНИЕ. Я попытался запустить этот тест, чтобы проверить, могу ли я воспроизвести ошибку, но ничего не нашел. Код выполнился правильно, и приложение запустилось без проблем с совместным доступом к файлам.

    for (int i = 0; i < 50; i++)
    {
        using (SqlCeEngine engine = new SqlCeEngine(Resources.SqlCeConnectionString))
        {
            //Log.Info("Starting database Verification.");
            if (!engine.Verify())
            {
                Log.Warn("Database failed verification.");
                engine.Repair(null, RepairOption.RecoverAllOrFail);
                Log.Info("Database successfully repaired.");
            }
            else
            {
                Log.Info("Verified" + i);
            }
        }
    
        if (File.Exists(Resources.BackupDatabaseFileLocation))
        {
            File.Delete(Resources.BackupDatabaseFileLocation);
        }
    
        File.Copy(Resources.DatabaseFileLocation, Resources.BackupDatabaseFileLocation);
        Log.Info("File Copied " + i);
        GetStartupData();
    }
    

Заранее большое спасибо за любую информацию, которую вы можете предоставить.


person neverseenjack    schedule 16.05.2013    source источник
comment
Могу только предположить, что ни проверка базы данных, ни резервное копирование еще не закрыли файл. Файловые операции могут кэшироваться и по-прежнему выполняться в фоновом режиме при попытке доступа к БД. Для file.write и т. Д. У нас есть явный метод Flush (), но я не вижу этого для file.copy. Что произойдет, если вы поместите доступ к базе данных (открытое) в блок try catch и повторите попытку доступа несколько раз с некоторой задержкой между ними?   -  person josef    schedule 16.05.2013
comment
@josef Я попробую завтра первым делом. Я предположил, что это был один из этих методов сохранения файла открытым, но я не могу сказать, какой из них. Я знаю, что SqlCeEngine открывает соединение с FileMode = Exclusive, что вызовет ошибку, если что-то попытается получить к нему доступ, но я немедленно избавляюсь от него, что должно снять блокировку. Интересно, будет ли у File.Copy эксклюзивная блокировка?   -  person neverseenjack    schedule 16.05.2013


Ответы (1)


Я обнаружил, что не все классы реализуют IDisposable так, как должны. Например, ядро ​​базы данных Microsoft OLE JET не закрывает соединение с базой данных при вызове из оператора using.

У вас могут быть эти проблемы здесь.

Я бы посоветовал для начала явно вызывать Close() для ваших подключений. Если это не решит проблемы, вы можете добавить явный вызов Dispose().

Также может быть, что сборщик мусора (GC) не имел возможности обработать весь IDisposable код до того, как ваше приложение снова попытается получить к нему доступ.

person jp2code    schedule 16.05.2013
comment
Я тоже подумал об этом, но нашел пару вещей, которые заставили меня поверить в обратное: - person neverseenjack; 16.05.2013
comment
1. Это сообщение - в социальных сетях .msdn.microsoft.com / Forums / en-US / sqlce / thread / 2. SqlCeEngine не предоставляет явного метода Close. Я использовал dotPeek, чтобы посмотреть на класс, и его метод Dispose, похоже, правильно очищает ресурсы. Вызов Dispose () внутри оператора using является избыточным. - person neverseenjack; 16.05.2013
comment
... и я вижу, что ActiveSync тоже не подозреваемый. Можете ли вы прослушивать и обрабатывать, когда ваше устройство переходит в режим ожидания и выходит из него? Если это так, вы можете поэкспериментировать с поддержанием открытого соединения, пока ваше устройство не перейдет в режим ожидания, закройте соединение, а затем повторно установите соединение, когда устройство выйдет из режима ожидания. ... хотя лично мне не нравится идея поддерживать открытую связь. - person jp2code; 16.05.2013
comment
Хотя это может решить эту проблему, я чувствую, что постоянное открытое соединение может вызвать целый ряд других проблем, связанных с особенностями (но не только) в сценарии цикла приостановки / пробуждения, который вы описали. Не говоря уже о том, что на этом этапе также потребуется полная переработка моей реализации, которую мне определенно трудно продать. :-) - person neverseenjack; 17.05.2013