Oracle托管驱动程序可以正确使用异步/等待吗?

时间:2015-03-12 17:42:26

标签: c# .net oracle async-await odp.net-managed

我试图使用async / wait .NET功能进行Oracle查询。结果集非常大,需要大约5-10秒才能恢复。 Window_Loaded挂起了UI线程,本质上我想使用async / wait在后台进行查询,然后使用结果更新数据视图。

这是Oracle驱动程序问题还是代码错误?例如。这是同步而不是异步完成的事情吗?我使用的最新Oracle.ManagedDataAccess来自Oracle的网站。

async Task<DataTable> AccessOracleAsync()
{
    DataTable dt;
    using(OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["connStr"].ConnectionString))
    using (OracleCommand cmd = new OracleCommand(@"SELECT * FROM myTbl", conn))
    {
        await conn.OpenAsync();
        using (var reader = await cmd.ExecuteReaderAsync())
        {
            dt = new DataTable();
            dt.Load(reader);                        
        }
    }

    return dt;
}

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    await AccessOracleAsync();
}

我试过这个,它仍然在用户界面陷入僵局:

async Task<DataView> AccessOracleAsync()
{
        DataTable dt;
        using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["connStr"].ConnectionString))
        using (OracleCommand cmd = new OracleCommand(@"SELECT * FROM myTbl", conn))
        {
            await conn.OpenAsync().ConfigureAwait(false);
            using (DbDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false))
            {
                dt = new DataTable();
                await Task.Run(() => dt.Load(reader)).ConfigureAwait(false);
            }

        }
        return dt.AsDataView();
}

private async void Window_Loaded(object sender, RoutedEventArgs e)
{
    Data1.ItemsSource = await AccessOracleAsync();
}

所以最后,我将方法更改为类似的东西,使其不会死锁。看来我有正确的想法,只是Oracle Managed库同步实现了Async方法(只是为了符合接口)。

private async Task<DataView> AccessOracleAsync()
{
        DataTable dt = new DataTable();
        using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings["connStr"].ConnectionString))
        using (OracleCommand cmd = new OracleCommand(@"SELECT * myTbl", conn))
        {
            await Task.Run(() =>
                {
                    conn.Open();
                    using (DbDataReader reader = cmd.ExecuteReader())
                    {
                        dt.Load(reader);
                    }
                }).ConfigureAwait(false);

        }
        return dt.AsDataView();
}

2 个答案:

答案 0 :(得分:14)

没有。托管驱动程序不支持async / await

您可以调用这些方法,因为它们必须实现以符合接口定义,但代码实际上是同步的。如果您愿意,可以使用Task.Run,但是您无法同时进行两次调用(Oracle会威胁它们同步)。

答案 1 :(得分:9)

(我将此作为答案,因为它似乎是&#34;解决方案&#34;让Oracle托管驱动程序正确支持异步。)

我在甲骨文的网站上找到了old thread(来自2010年),甲骨文公司表示他们不支持它。您可以vote(必须拥有Oracle帐户)才能包含该功能。 5年后,遗憾的是只获得了60票。