Using CallContext For Request-Specific Storage

P

Pham Nguyen

Hello,

Is it appropriate to use the CallContext class for storing
request-specific data? I have a set of business objects that
I'm building. Each class contains a hashtable that maps from a key to
an object. Whenever a constructor is called, the hashtable is
consulted first to see if an object with that key already exists. If
it doesn't, the object is pulled from the database and put inside of
the hashtable. I'd like the hashtables to be specific to an execution
context -- for instance, if two different web requests create a Person
object with an ID of 100, I'd like them to get 2 different objects.
But within one executing web request, if a Person object with an ID of
100 is created twice, I'd like the same object to be returned both
times.

The business objects might be used outside of a web context, so I
can't rely on the HttpContext.Items collection -- would CallContext be
an appropriate alternative? It resides in the
System.Runtime.Remoting.Messaging namespace, which gives me pause.
I've copied below the two relevant methods for fetching and storing an
object. Thanks in advance for any help!

public static Person GetByKey(int id)
{
object o = CallContext.GetData("PersonMap");
if (o != null)
{
Hashtable map = (Hashtable)o;
return map[id] as Person;
}
else
return null;
}
public static void AddToMap(Person person)
{

if (CallContext.GetData("PersonMap") == null)
{
Hashtable map = new Hashtable();
map.Add(person._id, person);
CallContext.SetData("PersonMap", map);
}
else
{
Hashtable map = (Hashtable)CallContext.GetData("PersonMap");
map.Add(person._id, person);
}
}
 
B

bruce barker

no, as the CallContext is tied to a thread. if your business object is
called from an asp.net page, its not guaranteed that it will be called by
the same thread thoughout the processing of a single page request (see
asp.net thread agility).

a better design would be to use instance data in you business object, and
not use static methods. also the code would be simpler and faster.


-- bruce (sqlwork.com)
 
P

Pham Nguyen

bruce barker said:
no, as the CallContext is tied to a thread. if your business object is
called from an asp.net page, its not guaranteed that it will be called by
the same thread thoughout the processing of a single page request (see
asp.net thread agility).

a better design would be to use instance data in you business object, and
not use static methods. also the code would be simpler and faster.

These object maps need to be globally visible throughout a request
(but expire at the end of it). I don't see how I would do this with
instance data, unless I pass an object containing the maps around
everywhere I might need to do a lookup.

I've been thinking of putting the maps in a separate class from the
business objects, one that tests whether the code is executing from
the web or not, and uses HttpContext and CallContext to store the
maps, respectively...
 
F

Finn Hart

Pham Nguyen wrote:
Pham said:
Is it appropriate to use the CallContext class for storing
request-specific data?

Actually, CallContext does appear to be appropriate per Pham's request.

Here's fact that contradicts Bruce's assertion: HttpContext.Current is
guaranteed to be constant during the execution of an asp.net page,
regardless of whether the thread executing the page changes under the
hood (as Bruce states can happen). HOWEVER, HttpContext.Current itself
uses CallContext (you can use ildasm.exe or reflector to discover
this).

CallContext seems to be what Pham is looking for - something that "like
HttpContext.Current.Items, but doesn't require HttpContext".
Alternatively, you could state the requirement as "a ThreadStatic
storage field that is reset to null when threads are recycled in the
thread pool." (threadstatics retain their value when they are
recycled).

As an aside, the documentation for CallContext is pretty slim, so it
seems like this behavior (which is quite useful) might change in future
releases of the framework. If so, I would just pull out Reflector
again to find out what HttpContext.Current is using...
 
S

Scott Allen

Hi Finn:
Here's fact that contradicts Bruce's assertion: HttpContext.Current is
guaranteed to be constant during the execution of an asp.net page,
regardless of whether the thread executing the page changes under the
hood (as Bruce states can happen). HOWEVER, HttpContext.Current itself
uses CallContext (you can use ildasm.exe or reflector to discover
this).

It is dangerous to rely on hidden implementation details like this.
Context.Items is the place for request specific data. Relying on
CallContext or any other form of thread local storage could be a
problem in future version of the framework.
 
F

Finn Hart

Hi Scott,
It is dangerous to rely on hidden implementation details like this.
Context.Items is the place for request specific data. Relying on
CallContext or any other form of thread local storage could be a
problem in future version of the framework.

You're right - it is a risky thing to do. However, Pham needs
something that can work outside of a web context, so
HttpContext.Current isn't guaranteed to be non-null (and thus using
Context.Items isn't a possibility).

Faced with that requirement, the question becomes "how can I get
something _like_ HttpContext.Current?" An obvious answer is "figure
out how HttpContext does it" - you just might learn something along the
way.

I don't think this approach is _necessarily_ risky - after all, what
better way to learn about the framework then to read the code of some
object that is very close to your requirements? What makes it risky in
this situation is that the documentation of CallContext is so slim that
one cannot tell if the behavior is guaranteed or incidental.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,998
Latest member
MarissaEub

Latest Threads

Top