33

I was trying to make an Oracle query with the async/await .NET feature. The result set is pretty large and takes about 5-10 seconds to come back. The Window_Loaded is hanging the UI thread, essentially I wanted to use async/wait to do the query in the background and then update a dataview with the result.

So is this an Oracle driver issue or a code error? E.g. is something here being done synchronously instead of asynchronously? I'm using the latest Oracle.ManagedDataAccess I could get from Oracle's web-site.

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();
}

I tried this, and it is still blocking the UI:

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();
}

So in the end, I changed the method to something like this to make it not block. It appears I had the right idea, just that the Oracle managed library implemented the Async methods synchronously (only to comply with the interface).

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();
}
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
user17753
  • 3,083
  • 9
  • 35
  • 73
  • What you could try is to take the code dt.Load(reader); into a task like await Task.Run(() => dt.Load(reader)); Further the code looks good to me. – Martijn van Put Mar 12 '15 at 18:26
  • 1
    FYI, I emailed Oracle about the async support and received a response: "I don't have any new info on when to expect async for ODP.NET, Managed Driver." – mason Mar 23 '15 at 19:01
  • They published a new version 18.3 (last one was 12.2) 7 days ago. https://www.nuget.org/packages/Oracle.ManagedDataAccess/18.3.0 maybe this new one really is async. Can anyone confirm that? – lmcarreiro Sep 05 '18 at 12:16
  • 4
    @lmcarreiro Of course it isn't. Oracle has no plans to implement this. The only solution to this problem is to move to... well, almost literally any other database, since the rest don't seem to have Oracle's problems. – EKW Oct 18 '18 at 12:50
  • I edited the text in the question and replaced the "deadlock" with "block", which I think is more accurate. A deadlock is something that blocks forever, not just for some seconds. – Theodor Zoulias Feb 24 '21 at 11:09

4 Answers4

25

No. The managed driver does not support async / await.

You can call those methods, since they must be implemented to comply with the interface definition, but the code is actually synchronous. You can use Task.Run if you want to, but you can't have two calls at the same time (Oracle will threat them synchronous).

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • 7
    Thanks, when trying to pickup `async`/`await` it's super confusing for some methods labeled `async` to actually be implemented synchronously. – user17753 Mar 13 '15 at 14:15
  • @user17753: True. They need to be there to comply to the interface. Else, they wouldn't have been there. – Patrick Hofman Mar 13 '15 at 14:18
  • 11
    @user17753 Not only is it confusing, [it's frustrating](http://stackoverflow.com/questions/28544557/async-i-o-intensive-code-is-running-slower-than-non-async-why/29034733#29034733). – mason Mar 13 '15 at 14:25
  • I think Microsoft decided, "well, if they're not going to play nice and support our shiny new concurrency syntax, we're gonna make them look bad" – tacos_tacos_tacos Jun 24 '15 at 06:48
  • 6
    Microsoft doesn't implement the driver. Oracle does. @tacos_tacos_tacos – Patrick Hofman Jun 24 '15 at 06:50
  • 2
    Although that is not the case, Oracle could even not be aware they should override the implementation of async method inherited from `DbConnection`, `DbCommand`, ... This implementation just falls back on the synchronous method. ODAC was existing prior to those async methods on ADO.Net types. They were added on ADO.Net types without being abstract very likely because otherwise it would have been a breaking change for all providers. As for choosing between a default implementation throwing exceptions or fallback-ing on synchronous, I personally prefer the later. And that was Microsoft choice. – Frédéric Jun 16 '17 at 16:06
  • 9
    @Frédéric They do know, because I spoke with their guy in charge of their .NET drivers several years ago. I would much rather they throw NotImplementedException rather than falsely lead you to believe they have asynchronous support. – mason Nov 15 '17 at 00:46
13

(I'm leaving this as an answer since it appears to be the "solution" to getting the Oracle managed driver to properly support async.)

I found an old thread (from 2010) on Oracle's site where Oracle PM's say they don't support it. You can vote (must have an Oracle account) to have that feature included. After 5 years it's sadly only gained 60 votes.

mason
  • 31,774
  • 10
  • 77
  • 121
  • 3
    Well it's 2019 now and nothing has changed. – bokibeg Aug 21 '19 at 15:29
  • From Oracle .NET Team: "No async support yet. That's a project we're working on as well." There is hope yet for us that still have to use Oracle. https://twitter.com/OracleDOTNET/status/1227374014177280000 – DoubleJ Feb 12 '20 at 22:49
  • 4
    @DoubleJ they said they’d work on it 5 years ago too. Do you really trust Oracle? – mason Feb 13 '20 at 02:11
  • Here we are, almost 6 years later, still waiting. gg Oracle. – DoubleJ Mar 03 '21 at 00:42
  • 1
    It's 2021 now and nothing has changed. No async support yet. – fsbflavio Mar 17 '21 at 01:26
  • 3
    It's 2022, no async support, no voting... Oracle left us, so People have probably left Oracle. – Larry Jun 09 '22 at 12:06
  • 2
    I revisit this thread periodically to amuse myself. We are forever married to Oracle. I found this awhile back, they said Q4 2022 originally, but it's already been pushed to 2023. Someday Oracle, someday... https://github.com/oracle/dotnet-db-samples/issues/144 – DoubleJ Jul 21 '22 at 22:46
3

There is a Github issue which has set the milestone to the 23C release for ODP.NET. There has also been announced demostration of async implementation during Oracle Cloud World 2022.

tronda
  • 3,902
  • 4
  • 33
  • 55
  • We're in Q2 2023 now and the current ODP.net version is still 21c (https://www.oracle.com/database/technologies/net-downloads.html). Seems like Oracle is not able to provide us with a release date or it is not very good at making it clear... – vc 74 May 22 '23 at 08:54
  • The issue is now closed and a dev release available. – Giorgi Aug 14 '23 at 19:32
3

After 10+ years Oracle has finally released a dev (beta) version of the managed driver with async/await support.

Github issue:
https://github.com/oracle/dotnet-db-samples/issues/144#issuecomment-1656674986

Oracle Instructions:
https://docs.oracle.com/en/database/oracle/oracle-database/23/odpnt/featAsyncPipelining.html#GUID-27CA3823-92BA-489A-9356-9EAA7B86A4FE

Nuget Package for .NET Core:
https://www.nuget.org/packages/Oracle.ManagedDataAccess.Core/23.2.0-dev

You need to enable prerelease in Visual Studio if you want to install it since it is only in development (beta).

DoubleJ
  • 419
  • 6
  • 7