【问题标题】:There is a file sharing violation. SQL Server CE 3.5 SP2存在文件共享冲突。 SQL Server CE 3.5 SP2
【发布时间】:2013-05-10 18:49:55
【问题描述】:

我在使用 SQL Server CE 3.5 SP2 数据库的 .NET CF 应用程序中遇到了这个随机问题。

当 CF 应用程序启动时,它会执行数据库维护以验证 .SDF 数据库文件以使用 SQL Server CE Engine 类进行检查:

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。积极的 必须打开同步才能使其正常工作。这 与之通信的台式计算机是 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();
    }
    

非常感谢您提供的任何信息。

【问题讨论】:

  • 我只能假设数据库验证或备份尚未关闭文件。当您尝试访问数据库时,文件操作可能会被缓存并仍在后台运行。对于 file.write 等,我们有一个明确的 Flush() 方法,但对于 file.copy,我没有看到。如果您将数据库访问(打开)放在 try catch 块中并重试访问几次,中间有一些睡眠会发生什么?
  • @josef 我明天会尝试第一件事。我认为这是保持文件打开的其中一种方法,但我不知道是哪一种。我知道 SqlCeEngine 打开与 FileMode=Exclusive 的连接,如果有东西试图访问它会导致错误,但我会立即处理它应该释放锁。我想知道 File.Copy 是否也会对其进行排他锁?

标签: windows-mobile compact-framework sql-server-ce windows-mobile-6.5


【解决方案1】:

我发现并不是所有的类都像他们应该的那样实现IDisposable。例如,Microsoft 的 OLE JET 数据库引擎在从 using 语句调用时不会关闭数据库连接。

您可能会遇到这些问题。

我建议,首先,在您的连接上明确调用Close()。如果这不能解决问题,您可以添加对Dispose() 的显式调用。

也可能是垃圾收集器 (GC) 在您的应用程序再次尝试访问之前没有机会处理所有 IDisposable 代码。

【讨论】:

  • 我也想到了这一点,但我发现一些事情让我不相信:
  • 1.这篇文章 - social.msdn.microsoft.com/Forums/en-US/sqlce/thread/… 2. SqlCeEngine 不提供明确的“关闭”方法。我使用 dotPeek 查看该类,它的 Dispose 方法似乎正在正确清理资源。在 using 语句中调用 Dispose() 是多余的。
  • ...我认为 ActiveSync 也不是嫌疑人。当您的设备进入和退出挂起模式时,您是否可以监听和处理?如果是这样,您可以尝试保持打开连接,直到您的设备进入挂起模式,关闭连接,然后在设备退出挂起模式时重新建立连接。 ...虽然,我个人不喜欢保持开放连接的想法。
  • 虽然它可能会解决这个问题,但我觉得一直打开连接可能会导致一系列完全不同的头痛,在您描述的挂起/唤醒周期场景中的特殊性(但不仅仅是)。更不用说它还需要在这一点上对我的实现进行彻底的重新设计,我肯定很难卖掉它。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多