ApplicationContext.LogicalExecutionLocation wrong if nested local data portal calls made?

ApplicationContext.LogicalExecutionLocation wrong if nested local data portal calls made?

Old forum URL: forums.lhotka.net/forums/t/6874.aspx


rsbaker0 posted on Wednesday, April 29, 2009

I copied the LogicalExecutionLocation support from CSLA 3.6.2 into 3.5.1. Of course, I could have bungled it, but it seemed simple enough.

Anyway, what seems to happen is that if you make another data portal call while in the middle of the first one, the call to ClearContext() when returning from the nested call will unconditionally set your LogicalExecutionLocation back to Client, even though you are still in the middle of the first call.

I'd think some sort of stack or counter-based mechansim would be required if this was going to work when making nested calls, as any nested local data portal call made before the outer call completes one should not change the execution location (assuming I'm understanding the intent correctly)

Also, the location is implemented as a static enum variable, so I'm curious as to how this would work if you had a multi-threaded application with different threads making data portal calls? Perhaps this really needs to be a value stored in the LocalContext rather than a shared static one?

rsbaker0 replied on Wednesday, April 29, 2009

Just to see what would happen, I replaced the implementation with this one and it seems to work properly. Basically I'm just storing a data portal call depth in the local context. Any set of location to Server increments the depth, and a location set back to Client decrements it. I definitely get to a depth of at least 2 in my current application running over the local data portal.

    /// <summary>
    /// Gets a value indicating the logical execution location
    /// of the currently executing code.
    /// </summary>
    public static LogicalExecutionLocations LogicalExecutionLocation
    {
        get
        {
            int nDepth = 0;
            object o = LocalContext["LogicalExecutionLocation"];
            if (o is int)
                nDepth = (int)o;

            return nDepth > 0 ? LogicalExecutionLocations.Server : LogicalExecutionLocations.Client;
        }
    }

    internal static void SetLogicalExecutionLocation(LogicalExecutionLocations location)
    {
        int nDepth = 0;
        object o = LocalContext["LogicalExecutionLocation"];
        if (o is int)
            nDepth = (int)o;

        if (location == LogicalExecutionLocations.Server)
            nDepth++;
        else if (nDepth  > 0)
            nDepth--;

        LocalContext["LogicalExecutionLocation"] = nDepth;
    }

 

(I can see how this is might need to be tweaked for a remote data portal implementation as anything running on the remote portal is always server side so this is overkill)

RockfordLhotka replied on Thursday, April 30, 2009

This does need looking into - thank you for calling out the issues.

swegele replied on Wednesday, September 09, 2009

I just ran into this. I have logic in my DAL that checks if I am on the server side of the DataPortal (logically) before attempting to make a connection to the DB.

This problem causes a nested call to fail.

RockfordLhotka replied on Wednesday, September 09, 2009

This issue is fixed in a recent version (3.6.3 or 3.7).

swegele replied on Wednesday, September 09, 2009

Yes...fixed in 3.8

from change log
______________________

LogicalExecutionLocation (090721)
http://www.lhotka.net/cslabugs/edit_bug.aspx?id=395

Store LogicalExecutionLocation in LocalContext so it is safe on the server and in multi-threaded client scenarios.



Also change the data portal so LogicalExecutionLocation works with nested calls. To do this I changed SetContext and ClearContext to be instance methods so they can work with an _oldLocation field to handle the nesting.

Copyright (c) Marimer LLC