ASP.NET MVC – Stateless Web Applications and DBContext Issues

asp.net-mvccentity-framework

In Entity Framework, the DBContext class is said to implement the unit-of-work pattern. As I interpret this, it means that if you make a DBContext, manipulate its data, and then dispose of it, then these manipulations will either all succeed together or all fail together, and get rolled back. Moreover, there is the potential for a performance benefit, as the underlying infrastructure gets to see everything you're doing at once, and do things like combine operations. This instantiate/manipulate/dispose sequence would typically comprise a using block in most C# code.

This all seems eminently logical, but when I try to read about DBContext as it performs in an ASP.NET MVC application, I run into statements I just don't quite get, e.g.:

"DBContext relies on several managed features and flags that keep track of changes in items that have been queried from the datastore… [t]he stateless nature of ASP.NET MVC prevents the default functionality of Entity Framework from working, however."

(Developing ASP.NET MVC 4 Web Applications, Exam Reference 70-486 by William Penberthy, Microsoft, 2013, p. 5)

I'd really like some more specifics about this supposed breakdown in the "default functionality of Entity Framework". Am I to understand that if I build a using block around a DBContext and some manipulations thereon, say, in a controller method, then a trip through this using block no longer comprises a single unit-of-work? Can I no longer expect each set of manipulations to either get committed as a whole unit or rolled back as a whole unit under ASP.NET MVC?

Or, alternately, does the breakdown in the "default functionality of Entity Framework" relate solely to the performance benefits obtainable from the use of a DBContext? I guess one possible interpretation of the statement I'm asking about is just that multiple, concurrent requests (e.g. to my example controller method) won't have their database manipulations combined for increased performance.

For example, if 999 people update a single column of the same row in a database, in quick succession, then all of these updates will end up happening individually… which is something I wouldn't have thought required mentioning. It certainly doesn't mean that using blocks build around a DBContext work any differently in ASP.NET MVC.

In any case, if you understand the statement I quoted better than I do, then I would appreciate your help in understanding it.

Best Answer

The problem amounts to maintaining server state in an application environment that is stateless by design.

Consider what happens when you implement a shopping cart. Shopping carts involve several steps: you must choose the items you want (usually one at a time while looking at product pages), put in your address, select the shipping type, supply a method of payment, and finalize the order.

Each page that you submit to the server during this process is essentially a complete transaction. REST architecture assumes that, once the request/response cycle is complete, there's nothing left to do.

To track progress on a shopping cart using a DBContext, one would have to open a DBContext, say, whenever the user puts their first item into the shopping cart. The problem is, where do you hold this object open? DBContexts are normally closed when the page is submitted. What happens if several users open shopping carts? Now I have to keep track of all those DBContexts. What happens if someone abandons a shopping cart?

What we're really talking about are SESSIONS. Martin Fowler talks extensively about SESSION state in his P of EAA book, including whether to store SESSION state on the server or the client, and the advantages and disadvantages of each approach.