开发者

Managing a Linq to SQL Datacontext in a WCF service using a DataContextFactory

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)
{
开发者_如何学Python    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;
}


I got the same problem. I use Castle.Windsor IOC container + "PerWebRequest" lifestyle, and it works in a similar way as your factory under the hood.

I'm still trying to find the perfect solution for my needs, but I have an intermediate solution that can help you : making your WCF service run with a HttpContext :

1) In your WCF project, ask for ASP.Net compatibility

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
</system.serviceModel>

2) Add an attribute to your service to manage this compatibility

[AspNetCompatibilityRequirements(
    RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class MyService : IMyContract
{
  ...
}

Source : Code rant

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜