Asynchronous SQLDataTable from ExecuteReaderAsync - makes sense? - asp.net

I am using ASP.NET 4.5, with <httpRuntime targetFramework="4.5" /> set.
I have an old data helper library method that returns a SQLDatatable using SQLDataAdapter.Fill().
I want to add a method to return Task(of SQLDatatable) - an async equivalent of the old method.
The code I have is like below (only the portion of code that matters is included):
Note:
GetConnectionString() returns the sql connection string
GetSqlCmd(...) returns a SQLCommand object
LogError() logs any exception
Using conn As New SqlConnection(GetConnectionString())
Try
cmd = GetSqlCmd(strSQL, conn, hash)
Await conn.OpenAsync().ConfigureAwait(False)
Using datareader = Await cmd.ExecuteReaderAsync().ConfigureAwait(False)
userDataTable.Load(datareader)
End Using
Catch ex As Exception
LogError(ex)
End Try
End Using
And the code works in the ASP.NET application, once I add await to the library method call.
The thing I'm not really sure is if the code above makes sense. Certainly the SQLDataReader is async, but SQLDataTable.Load(datareader) doesn't appear to use ReadAsync (as far as I can tell)...
Does this fact make the above code pointless - meaning, "ExecuteReaderAsync without ReadAsync" is pointless?

It is not pointless. Using async is not all or nothing. In a web app async IO is about block threads less. It is not required to not block them at all.
You have eliminated the blocking resulting from OpenAsync and ExecuteReaderAsync. Draining the reader is still synchronous.
That said, most web apps don't get any benefit at all from using async. For example it does not magically make your queries faster or add more capacity to the database server. So chose wisely.

It is not "pointless", rather it helps that specific piece of code scale better. You don't have to use it everywhere but if you need to improve scalability, you should as much as possible.
Async is not about making anything faster, it is about making an app scalable. It is misleading at best (and totally wrong at worst) for this answer to say "...most web apps don't get any benefit at all from using async. For example it does not magically make your queries faster or add more capacity to the database server".
The apps that will get the most from going async are those that require scalability. Here is another answer on SO that has more detail - Not much difference between ASP.NET Core sync and async controller actions
Not using async means your calls are blocking waiting for the db to do something. Using async means those threads that would've been blocking can actually do something else. This increases scalability. Microsoft's own Bing.com is internally run on SqlServer so SqlServer has no problem with scalability when designed and implemented correctly.

Related

How to add UserManagerExtension class methods in Asp.Net Core 2.0?

I am migrating my current project to core, and in my current project I have many synchronous method calls from UserManagerExtension class like Create, FindById, AddToRole etc. But despite thorough searching online I am not able to find the same in core.
Is it deprecated in core 2.0? If not, what is the namespace and how to include it?
As far as I can tell, they are gone. However, their existence was suspect even before. All the extensions did was simply run the async versions "synchronously", which basically means they spun off a task that blocked on the async call until it completed. While this technically satisfies having a "synchronous" method, it's actually really bad for web applications as you're sacrificing threads from your pool to do the work synchronously.
In ASP.NET MVC, it was a necessary evil, though, since there were many aspects that did not support async: child actions, action filters, etc. However, in Core, everything is async, and things happening in a web application space should be async. Therefore, there's simply no good reason to ever use sync methods, so that's probably why they no longer exist.
If you still need to run the async methods as sync, for some reason, you can simply block on them yourself:
var user = UserManager.FindByIdAsync(id).GetAwaiter().GetResult();
Be aware, though, that can deadlock in certain situations, because of the context shift. The two ways to avoid that are:
Use ConfigureAwait(false)
var user = UserManager.FindByIdAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
However, you cannot use ConfigureAwait(false) in something like an action method, since the context must be maintained in order to complete the response. You can use it in a method called by the action method, though:
private ApplicationUser GetUser(string id)
{
return UserManager.FindByIdAsync(id).ConfigureAwait(false).GetAwaiter().GetResult();
}
...
var user = GetUser(id);
Run it in a different thread
Task.Run(() => {
var user = UserManager.FindByIdAsync(id).GetAwaiter().GetResult();
// code here that needs `user`
});
As you can see, with this method the work you send off must be self-contained, so it's probably not a good fit in most scenarios. Also, again, this is extremely bad for web applications.
Long and short, there's not really a good way to run async as sync, and you should avoid it as much as possible. Async should be async all the way. That did use to be an issue in MVC, but now it's not with Core.

How bad is it to run an entire HTTP action method in separate thread using Task::Run()?

I'm writing web services in C++/CLI (not my choice) using Microsoft's Web API. A lot of functions in Web API are async, but because I'm using C++/CLI, I don't get the async/await support of C# or VB. So the fallback position is to use ContinueWith() to schedule a continuation delegate for reading the async task's result safely.
However, because C++/CLI also doesn't support inline anonymous delegates or managed lambdas, every delegate continuation must be written as a separate function somewhere. That quickly turns into spaghetti with the number of async functions in Web API.
So, to avoid the deadlock issues of Task<T>::Result, I've been trying this:
[HttpGet, Route( "get/some/dto" )]
Task< SomeDTO ^ > ^ MyActionMethod()
{
return Task::Run( gcnew Func< SomeDTO ^ >( this, &MyController::MyActionMethod2 ) );
}
SomeDTO ^ MyActionMethod2()
{
// execute code and use any task->Result calls I need without deadlocking
}
Okay, so I know this isn't great, but how bad is it? I don't yet understand enough of the guts of Web API or ASP.NET to comprehend the performance or scaling ramifications this will have.
Also, what other consequences may this have that aren't necessarily related to performance? For example, exceptions get wrapped in an extra AggregateException, which represents additional complexity and work for handling exceptions.
Your memory usage will increase with your application's parallelism. For every concurrent call to MyActionMethod you will need a separate thread with its own stack. That will cost you about 1 MB of RAM for each concurrent call. If MyActionMethod runs long enough so that 10000 instances run at once, you're looking at 10 GB of RAM. There is also CPU overhead in setting up each thread.
If concurrency is low, dropping async support won't be a problem. In that case, don't bother with Task::Run. Just change MyActionMethod to return SomeDTO^ (no Task wrapper).
Another potential concern is that lose easy use of cancellation tokens. However, for Web API it's usually fine to just let an exception propagate back to Web API, which ends up cancelling the synchronous call anyway.
Finally, if you were planning on performing any operation within your action method in parallel, you'll still need to use ContinueWith to accomplish that. Going non-async by default means you'll always perform one operation at a time. Fortunately, it's often just fine to do so.
Okay, so I know this isn't great, but how bad is it?
It's difficult to answer this without load-testing your specific scenario. But you can walk through the known semantics (taken largely from my blog).
First, when a request comes in, ASP.NET executes your handler on a thread pool thread within that request context. Your request handler calls Task.Run, which takes another thread from the thread pool and executes the actual request logic on it. The handler then returns the task returned from Task.Run; this releases the original request thread back to the thread pool.
Then, the Task.Run delegate will block on any asynchronous parts. So, this pattern has the scaling disadvantages of a regular synchronous handler, plus an extra thread context switch. Also, it uses a thread from the ASP.NET thread pool, which is not necessarily a bad thing, but in some scenarios it may throw off the ASP.NET thread pool heuristics.
Also, what other consequences may this have that aren't necessarily related to performance? For example, exceptions get wrapped in an extra AggregateException, which represents additional complexity and work for handling exceptions.
Yes, the exceptions from any .Result or Wait() calls will be wrapped in AggregateException. You may be able to avoid this by calling .GetAwaiter().GetResult() instead.
Another important consideration is that the code executing within the Task.Run is executing without a request context. So, ambient data like HttpContext.Current, current culture, thread principal, etc. are not going to be set correctly. You'll have to capture any important data before calling Task.Run and pass it down manually.

Asp.net web api + entity framework: multiple requests cause data conflict

I'm developing an app with VS2013, using EF6.02, and Web API 2. I'm using the ASP.NET SPA template, and creating a RESTful api against an entity framework data source backed by a sql server. (In development, this resides on the SQL Server local instance.)
I've got two API methods so far (one that just reads data, one that writes data), and I'm testing them by calling them in the javascript. When I only call a single method in my script, either one works perfectly. But if I call both in script (without waiting for either's callback to fire), I get bad results and different exceptions in the debugger. Some exceptions state that the save can't be completed because there are pending transactions. Another exception stated something about a conflict with other threads. And sometimes, the read operation fails with a null pointer exception when trying to read a result set.
"New transaction is not allowed because there are other threads running in the session."
This makes me question if I'm correctly getting a new DBContext per request. My code for this looks like:
static Startup()
{
context = new Data.SqlServer.AppDbContext();
...
}
and then whenever instantiating a unit of work, I access Startup.context.
I've tried to implement the unit of work pattern, and each request shares a single UOW object which has a single DBContext object.
My question: Do I have additional responsibility to ensure that web requests "play nicely" with eachother? I hope that this is a problem that others have already dealt with. Perhaps the errors that I'm seeing are legitimate in the sense that if one user's data is being touched, it is temporarily in an invalid state and if other requests come in at that exact moment, they indeed will fail (and I should code anticipating these failures). I guess that even if each request has its own DBContext, they still share the same underlying SQL data source so perhaps that's causing issues.
I can try to put together a testcase, but I get differing behavior depending on where I put breakpoints and how long I spend on them, reaffirming to me that this is timing related.
Thanks for any help or suggestions...
-Ben
Your problem is where you are setting your context. The Startup method is for when the entire application starts, thus any request made will all use the same context. This is not a per request setup, but rather a per application setup. As to why you are getting the errors, EntityFramework is NOT thread-safe. Since IIS spawns many threads to handle concurrent request, your single context is being used across multiple threads.
As for a solution, you can look into
-Dependency Injection frameworks (such as Ninject or Unity)
-place a using statement in your UnitOfWork classes
using(var context = new Data.SqlServer.AppDbContext()){//do stuff}
-Or, I have seen instances of people creating a class that gets the context for that request and stores it in the HttpContext.Cache[] element (using a unique name so you can retrieve it in another class easily), making it so that you will reuse the same context for the same request. Something like this:
public AppDbContext GetDbContext()
{
var httpContext = HttpContext.Current;
if (httpContext == null) return new AppDbContext();
const string contextTypeKey = "AppDbContext";
if (httpContext.Items[contextTypeKey] == null)
{
httpContext.Items.Add(contextTypeKey, new AppDbContext());
}
return httpContext.Items[contextTypeKey] as AppDbContext;
}
To use the above method, make a simple call var context = GetDbContext();
Note
We have all of the above methods, but this is specifically to the third method. It seems to work well with two caveats. First, do not use this in a using statement as it will not be available to any other classes during the scope of the request (you dispose it). And secondly, ensure that you have a call on Application_EndRequest that does actually dispose of it. We saw these little buggers hanging around after the request ended in memory causing a huge spike in memory usage.

WebApi loggin results async

I am using WebApi with Entity Framework to implement a REST service. I need to log the usage to the database. I can do this in the controller before it returns or in an ActionFilterAttribute. I want to be able to fire off a call to update the database, BUT I don't want to wait for completion. I want the response to return to the user without waiting for the update.
I was thinking about using a BackgroundWorker and passing in the objects.
Anyone have thoughts on if this is the good way to do this?
I think the question you should ask yourself is how much latency the database update can add to your overall response time. In most cases, it will be a lot simple to do the update as part of the request processing. Background worker is generally not a good solution but here is a good read related to that topic. If you absolutely need to do the database update outside of request processing, it will be better to consider a queueing mechanism like MSMQ, RabbitMQ, etc from the perspective of reliability.
I believe my performance problem is related to running in VS2012 debugger. When running the site directly, performance increased drastically. So I won't need to do any 'tuning tricks' if this proves out when deployed to test server.
Have you tried exploring NLog's async capabilities? We use NLog's async wrappers by wrapping a database logging target like so:
<targets async="true">
<target name="dbLog" xsi:type="Database" dbProvider="sqlserver" connectionString=".." />
.
.
</targets>
A quick startup on logging to MS SQL DB using NLog is found here
Moreover, you could make your logging method call async (.NET 4.5 required) and if you do not care for the result, choose not to await the method execution.
Look at this SO Thread for a sample NLog.config.

IHttpAsyncHandler causes UnathorizedAccessException

For the last couple of days of my X-mas holidays, I have been struggling with an UnathorizedAccessException when trying to READ a XML file on a remote share through my ASP.NET application using an implementation of the IHttpAsyncHandler a long with the IRequiresSessionState.
After much headache, and concluding that the code OUTSIDE the handler worked flawlessly (see: access granted), I thought it might be some threading issue, so I changed the IHttpAsyncHandler to IHttpHandler, and the problem disappears.
What is troubling me here is, that for test purposes, I did not actually make use if the IHttpAsyncHandler implementation (hence, I did not use BeginProcessRequest and EndProcessRequest - only the sync. version, ProcessRequest.
Can anyone try to explain the issue at hand?
There are some beneficial matters in using the handler asynchronously, as I could pre-cache the values to be delivered later in the application, but for that to work, I have to get pass the security issues that seems to only manifest when implementing the IHttpAsyncHandler.
Thanks in advance for your kind help - and happy holidays :-)
The ASP.NET infrastructure calls an async handler differently (regardless if the impl is truly async). Is it possible that you were relying on impersonation to access the network resource? My guess would be that the necessary WindowsIdentity didn't flow to the threadpool thread that actually handled the request (I've never tried using impersonation + async handler, but I've gotten nailed with other thread state flow issues in the past).
Regardless, a true async handler is expensive to implement correctly. Unless you're building on top of a lot of other async infrastructure (async file i/o, async DB client, etc), it doesn't do you any good (in fact, even in the best cases, async handlers hurt raw performance). I'd look to see if your performance needs really justify the extra hassle and overhead of an async handler (eg, you need to service many more concurrent requests than threads in the process, etc).

Resources