This thread looks to be a little on the old side and therefore may no longer be relevant. Please see if there is a newer thread on the subject and ensure you're using the most recent build of any software if your question regards a particular product.
This thread has been locked and is no longer accepting new posts, if you have a question regarding this topic please email us at support@mindscape.co.nz
|
Hi could you guys elaborate on how the new PerRequestUnitOfWorkScope behavior is actually implemented: PerRequestUnitOfWorkScope now detects if multiple unit of work types are being used within the same request http://www.mindscapehq.com/forums/Post.aspx?ThreadID=4220&PostID=14926 Also in IIS7 in the application_start "HttpContext.Current" might not be available how is this currenly handled ? (I fear possible NRE's when calling .Current on the scope from Application_OnStart. Second with the new behavior how do I actually dispose all the instances in End_Request ?
|
|
|
1. Previously, if you had a PerRequestUnitOfWorkScope<T1> and a PerRequestUnitOfWorkScope<T2> in the same HTTP request, they would try to stash the UOW associated with the request in the same place, leading to problems when the 'loser' tried to get their UOW back from that place. This no longer happens: PRUOWSs with different UOW types now store their UOWs separately, so you have have scopes for multiple UOW types in the same request. 2. That is correct, you cannot use a PerRequestUnitOfWorkScope outside a request. (The scope, as the name implies, is per-request: there's no meaningful 'request' scope when there's no request, as in the Application Start and End events.) Create a method-local unit of work directly using LightSpeedContext.CreateUnitOfWork(). 3. Iterate over the scopes, and for each scope call if (scope.HasCurrent) { scope.Current.Dispose(); }. If you're concerned about encapsulation, fear not: because the scopes are request-wide, you don't need to have access to the instances declared by the page or controller. Instead, you can create new PRUOWSs in EndRequest and, because they are part of the same request, they will refer to the same UOWs as the PRUOWSs used in your page or controller. |
|
|
This is what i assumed but i think you guys should document this new behavior here As a change between 3.1 and 4.0 and mention how you guys actually store a maximum of 1 unit of work per unitofwork type. Also if you can document the naming of the keys. It would be nice if the keys started with "Mindscape::lightspeed::UnitOfWork" or something equally unique so we could find all the keys we should dispose rather then newing new typed Scope and disposing those. I get how that works but its very counter intuitive. Perhaps a static method on PerRequestUnitOfWorkScope.DisposeAll() would already be a timesaver.
Thinking HttpContext.Current is available in App start and end events is still widespread and has only not been available since IIS7. I've only looked at the old code for PerRequestUnitOfWorkScope but there were no null checks around HttpContext.Current. I ended having something like this is my class:
}private RoutingModelUnitOfWork CreateUnitOfWork(out bool needsDisposal) { try { needsDisposal = false; return this.Scope.Current; } catch(Exception) { needsDisposal = true; return this.Context.CreateUnitOfWork(); } } protected void UsingUnitOfWork(Action<RoutingModelUnitOfWork> callback) { if (callback == null) return; bool needsDisposal = false; RoutingModelUnitOfWork uow = null; try { uow = this.CreateUnitOfWork(out needsDisposal); callback(uow); } finally { if (needsDisposal && uow != null) uow.Dispose(); } } protected TReturn UsingUnitOfWork<TReturn>(Func<RoutingModelUnitOfWork, TReturn> callback) { if (callback == null) return default(TReturn); bool needsDisposal = false; RoutingModelUnitOfWork uow = null; try { uow = this.CreateUnitOfWork(out needsDisposal); return callback(uow); } finally { if (needsDisposal && uow != null) uow.Dispose(); }....public class PageDataProvider : DataProviderBase, IPageDataProvider { public Page GetPageByName(string name) { var page = this.UsingUnitOfWork<Page>(uow=>uow.Pages.WithAggregate("BlockAggregate").FirstOrDefault(p => p.Name == name)); return |
|
|
Thanks for the feedback -- we'll try to update the docs. [quote user="poort80HS"]Also if you can document the naming of the keys. It would be nice if the keys started with "Mindscape::lightspeed::UnitOfWork" or something equally unique so we could find all the keys we should dispose rather then newing new typed Scope and disposing those.[/quote] No, you should not rely on the naming of the keys. This is an implementation detail and may change between nightly builds (already has on at least one occasion). We will not document or lock in the key names because this could prevent us extending functionality (as when we changed the key names to support multiple UOW types). [quote user="poort80HS"]I've only looked at the old code for PerRequestUnitOfWorkScope but there were no null checks around HttpContext.Current.[/quote] The current code null-checks in HasCurrent, so HasCurrent will return false if there is no HttpContext. I believe Current does not check, but your dispose code should check HasCurrent anyway, because otherwise you might wastefully create a UOW just in order to dispose it. I'll ask our Web guys if they have any recommendations on the app event disposal thing. Looking at the docs (http://www.mindscapehq.com/documentation/lightspeed/Building-Web-Applications-/Building-ASPNET-MVC-Applications) it looks like they are using Application.EndRequest but I will ask them to check on the IIS7 issue. |
|
|
On re-reading, I'm not quite sure I've understood your message correctly. As you say, HttpContext.Current is not available in the application Start and End events. This is nothing to do with IIS7. There is no request in progress when the application starts or ends, so you cannot use PerRequestUnitOfWorkScope<T> in those events. PerRequestUnitOfWorkScope really does mean per-request: no HTTP request, no UOW. What may be different in IIS7 is the invocation of the application EndRequest event (as distinct from the End event). Is that what you were referring to? As far as I know, and looking at the docs, during EndRequest there is still a HttpContext available, so all should be well. However I have heard that there were some changes to the way EndRequest got called in IIS7: I've been told these shouldn't affect PRUOWS, but I'll ask one of our Web guys to comment. |
|
|
You will want to use PRUOWS scope with the EndRequest event - make sure you are either using the named method (Application_EndRequest) or hooking the EndRequest event in the instance constructor so the event is triggered. For EndRequest the HttpRequest is present so you will have the existing UOW restored from HttpContext.Items where it is being held. As Ivan mentioned there is no request context present on Application_Start or End so the PRUOWS scope is not valid to use within these methods.
Jeremy |
|