I've been using Rick Strahl's DataContextFactory code (Linq to SQL DataContext Lifetime Management) in a data layer consumed by an ASP.Net application. It works great because the current datacontext is stored in the HttpContext.Items collection. I know that I'm reusing the same datacontext per web request.
However, I've been unable to use the factory successfully in an WCF service. On a non HttpContext app, the factory stores the datacontext in a thread data slot.
Thread.AllocateNamedDataSlot(key)
The problem is, no matter how I set up the ConcurrencyMode and InstanceContextMode in my service, the threads are reused each call and the same dataContext is reused. I don't want this. I only want a single datacontext to exist per service method call. Is there any way this can be achieved using a factory? I'm unable to find any unique information on each client call to use as an identifier for my datacontext so it won't be reused by other requests...regardless if it is the same client.
I want to consume my business layer and not access my data layer directly, but I'm afraid I might have to dictate my own units of work and datacontexts in my WCF service. Has anybody had any luck using some sort of factory for their datacontexts in a WCF service? I was hoping there was a way for my factory to know if it was being consumed by a WCF service and then handle the storing of the datacontext uniquely
public static T GetScopedDataContext<T>()
{
if (HttpContext.Current != null)
return (T)GetWebRequestScopedDataContextInternal(typeof(T), typeof(T).ToString(), null);
// What can I put here to handle WCF services differently?
return (T)GetThreadScopedDataContextInternal(typeof(T), typeof(T).ToString(), null);
}
And then what could be done here to achieve what I want?
static object GetThreadScopedDataContextInternal(Type type, string key, string ConnectionString)
{
if (key == null)
key = "__WRSCDC_" + Thread.CurrentContext.ContextID.ToString();
LocalDataStoreSlot threadData = Thread.GetNamedDataSlot(key);
object context = null;
if (threadData != null)
context = Thread.GetData(threadData);
if (context == null)
{
if (ConnectionString == null)
context = Activator.CreateInstance(type);
else
context = Activator.CreateInstance(type, ConnectionString);
if (context != null)
{
if (threadData == null)
threadData = Thread.AllocateNamedDataSlot(key);
Thread.SetData(threadData, context);
}
}
return context;
}