The Oracle Client (ODP.NET) that we are using to build a major web project put us in a really stupid bind last week, ultimately causing me to waste two days in search of something that wasn't really going to work in the first place.
I'm on something of an async/await binge with this project, since in C# and ASP.NET it's really easy to implement and possibly gives you great scalability benefits. So, one of the first things I did was to make all our ORACLE accessing code asynchronous. There's a particular section of the code which needs to call a bunch of stored procedures in a row, and I figured that since the procedures don't really rely on each other, we'd benefit quite a bit by making them asynchronous.
All of this was going swimmingly, until this error started popping up:
"Connection must be open for this operation"
Not being a total expert on this, I would still expect that, given an asynchronous execution, each async call would have its own connection and so this error should never happen. And yet, there it was, repeatedly being logged into our exception logger.
So, to the Google I went, and eventually came across this StackOverflow post saying that the Oracle Managed Driver does not support asynchronous operations.
Yes it does! I thought. It's got all these async methods! They wouldn't name them "async" unless they were actually asynchronous! (Apparently I've never been on the internet before.)
In fact, the Oracle Data Provider for .NET does contain a few asynchronous methods:
- ExecuteNonQueryAsync()
- ExecuteReaderAsync()
- ExecuteScalarAsync()
But the StackOverflow post says that these methods are not actually async, they are synchronous. So what's going on?
Browsing the features list for ODP.NET, I can't find any reference to asynchronous methods, the Task
or Task<T>
classes, or even the await
keyword. In fact, I can't find any documentation at all that says these async methods need to exist, and yet they do. The question is: why?
Microsoft's own documentation says the following:
"In Visual Studio 2012 and the .NET Framework 4.5, any method that is attributed with the async keyword (Async in Visual Basic) is considered an asynchronous method..."
But it never actually specifies that the method has to actually be asynchronous! Rather, only that the method should return a Task
or Task<T>
, and even that is only a convention!
All the above is to say: technically, ORACLE did nothing wrong by suffixing these method names with "async", since in fact they do return a Task
or a Task<T>
. In fact, they might even be useful since they can be asynchronous with other, non-ORACLE-accessing methods. But that wasn't my scenario, and how was I supposed to know about this in advance?
The question becomes: since the methods themselves are not actually executed asynchronously, are they of any use?
Short answer? Nope. At least not for my situation. If anything, it's more harmful than helpful.
As far as I can tell, the only reason the asynchronous versions of these methods exist is to conform to some mythical interface mentioned in the comments of this StackOverflow answer. Which just begs the question: why does the interface need these method declarations? Ultimately I decided to get out of the rabbit hole before digging myself too deep and remove all my asynchronous code that used ODP.NET.
So now, in addition to the two days I spent researching this and implementing it for ORACLE calls, I now have to spend at least half a day removing it. All because ORACLE made some "asynchronous" methods that aren't actually asynchronous. Thanks ORACLE!
To anyone else out there who has to use ODP.NET: don't bother with the asynchronous methods unless you really know what you are doing. They're a lot more trouble than they are worth.
And, if you do really know what you are doing, tell me in the comments what situations these bloody things might actually be useful!
Happy Coding!