并行使用 DBF 数据库的 C# ODBC 驱动程序未按预期工作

C# ODBC driver with DBF database in parallel not working as intended

大家好,这是我的最后一招,我想我弄错了,但无法摆脱困境

我试图在启动时加载一些旧的 DBF 文件以在新应用程序中创建我的数据上下文,但很快发现其中一些确实需要很长时间才能加载,有时甚至需要 1-2 分钟(这些是有时是 80-100MB 的数据库),这在应用程序开始时是不可接受的。 我的想法是并行加载它们,这意味着在最坏的情况下我有 1-2 分钟的加载时间(较大的)但是当使用秒表检查执行时间时我没有得到预期的 1-2 分钟但是相反,我得到了时间的总和,就好像我是一个一个地做的。

这是我为使用 obdc 适配器访问文件夹中的所有数据库而编写的代码,实际上,查询执行得非常快是适配器需要很长时间才能在 Datatable 中加载内容,我切换到使用“Parallel.Foreach()”没有得到任何结果后的任务我什至尝试打开和关闭后台获取但无济于事,有什么我可以尝试的或者这个驱动程序没有被更多人使用资源?

 public static List<DataTable> SelectAllParallel(string folder)
        {
            System.Data.Odbc.OdbcConnection conn = new System.Data.Odbc.OdbcConnection("Driver={Microsoft Visual FoxPro Driver};SourceType=DBF;SourceDB=" + folder + ";Exclusive=No;Collate=Machine;NULL=NO;DELETED=NO;BACKGROUNDFETCH=Yes;");
            List<string> Databases = new List<string>();
            foreach (var file in Directory.EnumerateFiles(folder, "*.dbf"))
                Databases.Add(Path.GetFileName(file));
                conn.Open();
            List<OdbcDataReader> QueryResult = new List<OdbcDataReader>();
            List<DataTable> Results = new List<DataTable>();
            var watch = new System.Diagnostics.Stopwatch();
            watch.Start();
            foreach (string database in Databases)
            {
                string strQuery = $"SELECT * FROM [{database}]";
                OdbcCommand command = new OdbcCommand(strQuery, conn);
                QueryResult.Add(command.ExecuteReader());
            }
            List<Task> tsk = new List<Task>();
            foreach(OdbcDataReader SingQuery in QueryResult)
            {
                tsk.Add(new Task(() => { DataTable dt = new DataTable();dt.Load(SingQuery); Results.Add(dt); }));
            }
            foreach (var tssk in tsk)
                tssk.Start();
            Task.WaitAll(tsk.ToArray());
            watch.Stop();


            conn.Close();
            var h = watch.Elapsed;
            return Results;
        }

您正在使用后台获取和多线程,这正是 Microsoft 警告您不要做的事情:

https://docs.microsoft.com/bs-latn-ba/sql/odbc/microsoft/thread-support-visual-foxpro-odbc-driver

Avoid using background fetch when you call the driver from multithreaded applications.

VFP ODBC 驱动程序是 thread-safe。这意味着,您可以从多个线程调用它(如果您避免后台获取)。但是,它不是multi-threaded。一次只执行一个查询。其他的被 VFP 用来同步访问其查询引擎的信号量阻塞。

使用 SELECT * FROM table 将所有行加载到内存中通常被认为是一种糟糕的方法。如果您只加载您需要的记录,您将获得更好的性能。 ODBC 驱动程序未针对 return 所有行进行设计和优化。

如果您的特定情况需要访问所有 table 中的所有行,例如,因为您的应用程序是一个将所有数据转换为不同格式的转换器,您可能会通过使用 C# 获得更好的性能DBF 库。但是,可能存在兼容性问题,因为这些库中的大多数仅实现较旧的 DBF 文件格式。您还应避免使用这些库进行编写,因为这可能会导致损坏。

如果您只是读取文件而不是稍后更改它们,并且如果您的文件位于网络共享上,则将整个文件复制到本地临时文件夹然后使用 ODBC 也会获得更好的性能驱动程序从临时文件夹读取。

这是因为VFP是同步读取记录的。它从文件服务器读取一条记录,并等到该记录已提供给客户端,然后再读取下一条记录。这会通过网络发送许多 IP 数据包(每个记录最多一个)。在这种情况下,网络延迟和数据包 trough-put 而不是带宽决定传输速度。使用本地文件则没有这些限制。