异步调用Access数据库

时间:2015-03-11 12:49:55

标签: c# .net ms-access task-parallel-library async-await

我正在开发一个与Access DB通信的c#应用程序。

目前,我正在使用c#5的async / await功能将db调用转换为异步调用。 在将数据库访问函数转换为异步对应项(即DbConnection.Open - > DbConnection.OpenAsync,DbDataReader.ExecuteReader - > DbDataReader.ExecuteReaderAsync ...)并插入await / async后,我最终得到了这样的方法: / p>

public async Task<Dictionary<int, ProductStockData>> getStockAmountPerOrderIntervalAsync() {
        var orderedProductsAndQuantities = await getOrderedProductsAndQuantitiesAsync().ConfigureAwait(false);

        string stockAmountPerOrderIntervalQuery = @"SELECT  {...}";

        using (OleDbConnection dbConnection = new OleDbConnection(ConnectionString)) {
            await dbConnection.OpenAsync().ConfigureAwait(false);

            using (OleDbCommand cmd = new OleDbCommand(stockAmountPerOrderIntervalQuery, dbConnection)) {
                DbDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false);

                {...}

                return productsAndStockAmountsPerInterval;
            }
        }
    }

调试时我发现两个异步调用总是在现场执行(而不是异步),阻塞调用线程(以及WPF应用程序)。

这个方法是从一系列方法中调用的,所有方法都用async修饰符标记并调用下一个方法,如下所示:

await [method]().ConfigureAwait(false);

在这个链的开头是来自ui线程的事件处理程序调用,如下所示:

async void mDbManager_OnConnectionEstablished() {
   await updateStockData(); // starting the chain of await call leading up to the aforementioned method call
   updateMissingProductsString();
}

在发现代码本身没有问题后,我开始研究数据库连接。 我正在使用Access数据库文件(.mdb),我当前的连接字符串是:

Provider=Microsoft.Jet.OLEDB.4.0;Data Source="{...}"

我也试过这个:

Provider=Microsoft.ACE.OLEDB.12.0;Data Source="{...}"

我做了一些研究,但我唯一能找到的是,在.Net 4.5之前你必须附加&#34; Asynchronous Processing = true&#34;到连接字符串以允许异步调用。但我正在使用.Net 4.5.1。即使我追加它,它也无法正常工作。

有人知道我是否还需要做其他事情才能启用对Access DB的异步调用?

编辑: 我也尝试使用带有此连接字符串的OdbcConnection:

Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq={...}

对异步数据库调用具有相同的阻止效果...

2 个答案:

答案 0 :(得分:0)

我认为您必须删除ConfigureAwait(false)调用才能使解决方案异步。否则,将不会进行编组,并且您的UI线程将被阻止。

一些偏离主题的建议:

  1. 使用SQL Server Express。它比Access更具可扩展性。
  2. 我还建议迁移到Entity Framework,它现在有一些很好的异步支持。只有当我必须完全控制数据访问或利用某些尚未支持的功能(即Oracle UDT)时,我才会直接使用ADO .NET

    希望这会有所帮助。

答案 1 :(得分:0)

如果您只需要取消阻止UI线程,则可以将阻止调用强制执行到这样的新任务上:

private async void MyButton_Click(object sender, EventArgs e)
{
  await Task.Run(() => getStockAmountPerOrderIntervalAsync());
}

这使您可以保留其余代码。

来源: https://blog.stephencleary.com/2013/11/taskrun-etiquette-examples-dont-use.html