当其他进程使用OleDB c#时,读取Excel文件

Nid*_*rma 7 c# excel

我试图每2秒读取一个excel文件,这个文件正在被其他RTD应用程序更新.

我能够通过Oledb连接读取此文件,但是当我尝试每2秒读取一次时会出现问题.在10次尝试中,它只能读取4-5次,而在其他尝试中,它会抛出异常.

连接字符串

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\nids\shes.xlsm;Extended Properties="Excel 12.0 Macro;HDR=Yes;IMEX=1"
Run Code Online (Sandbox Code Playgroud)

//opening connection to excel file

using (OleDbConnection connection = new OleDbConnection(constr))//constr = connection string
{
    try
    {  
        connection.Open();
        isconopen = true;
    }
    catch
    {
        dispatcherTimer2.Start();

        connection.Close();
        isconopen = false;
    }

    // If connection is ok , then query sheet  
    if (isconopen == true)
    {
        strcon = "SELECT * FROM [" + dsheet + "]";

        using (OleDbDataAdapter adapter = new OleDbDataAdapter(strcon, connection))
        {

            try
            {


                adapter.Fill(result);
                isread = true;
                adapter.Dispose();

                connection.Close();
            }
            catch 
            {

                isread = false;
                dispatcherTimer2.Start();

                adapter.Dispose();
                connection.Close();

            }

        }
     }

    //if able to retrieve data then call some other function 
    if (isread == true)
    {
        converToCSV(0);// for further processing
    }
Run Code Online (Sandbox Code Playgroud)

请帮助我,我从最近1个月开始尝试这个.请帮助请帮帮我

Adr*_*tti 6

遗憾的是OleDB驱动程序默认情况下会打开文件,然后当别人使用它时你就无法打开它,即使只是为了阅读.

两个考虑:

  • 其他应用程序可能会在几毫秒内完成其对文件的工作,因此最好再试一次
  • 驱动程序将始终打开文件锁定以进行写入(因此您无法通过OleDB打开它两次)但是它共享用于读取(因此您可以复制它).

这就是说我建议你应该在短暂的停顿后首先尝试打开它,如果它仍然在使用(你不能等待更多),那么你可以复制并打开它.

我假设你在HandlExcelFile()函数中有你的代码:

void HandleExcelFile(string path)
{
    try
    {
        // Function will perform actual work
        HandleExcelFileCore(path); 
    }
    catch (Exception) // Be more specific
    {
        Thread.Sleep(100); // Arbitrary

        try
        {
            HandleExcelFileCore(path);
        }
        catch (Exception)
        {
            string tempPath = Path.GetTempFileName();
            File.Copy(path, tempPath);

            try
            {
                HandleExcelFileCore(tempPath);
            }
            finally
            {
                File.Delete(tempPath);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

代码有点难看,所以只考虑它是编写自己的函数的起点.

注意事项:

  • 重试并不是一件坏事,而且这是解决这类问题的常用方法.例如,它就是Windows shell所做的事情(对网络来说更为正常).
  • 如果应用程序没有关闭文件,那么您可以复制(并读取)数据.如果您总是需要最新的数据,那么您只有一个选择:等待.如果您可以假设未保存的数据属于前一个时间范围(T-1,就像数字电子信号边缘处于时钟边缘时那样),那么就这样做并过得开心.

未经测试的解决方案:

我没有尝试这个,所以你必须自己做.实际上(我最初错了)你可以打开一个只读连接(通过扩展属性).如果这仅适用于连接或文件句柄和连接,则不会记录.无论如何,让我们尝试将您的连接字符串更改为:

Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\nids\shes.xlsm;Extended Properties="Excel 12.0 Macro;HDR=Yes;IMEX=1;ReadOnly=true"
Run Code Online (Sandbox Code Playgroud)

只是增加了一个ReadOnly=true在年底Extended Properties.

其他方案:

  • 我想到的唯一替代解决方案是...手动读取Excel文件(因此您可以打开它只是为了阅读).即使在这种情况下,其他应用程序可能还没有编写新数据(因此您将阅读数据).
  • 根本不要使用计时器.更改您的设计以使用a FileSystemWatcher,只有在通知它已被更改时才会读取该文件.
  • 适用时......只是不要使用共享文件作为IPC机制!好吧,您可能无法更改第二个申请,所以这可能不是您的情况.
  • 不要使用OleDB来读取Microsoft Excel文件,有许多第3部分免费库不能打开具有独占锁的文件,例如这个.
  • 不要直接从文件中读取数据,如果Microsoft Excel实例始终在运行,则可以使用COM interop来获取通知.检查这个一般文章有关COM加载项和这个看你怎么可以使用Office互操作的C#应用程序连接到现有的Microsoft Excel实例.

  • @NidhiSharma [阅读本文](http://support.microsoft.com/kb/291392/en-us),了解COM加载项的一般介绍.试试[本文](http://support.microsoft.com/kb/316126/en-us),它即使有点旧也可以工作,看看如何附加到正在运行的Excel实例. (2认同)