1

我一直在 ASP.Net 应用程序使用的数据层中使用 Rick Strahl 的 DataContextFactory 代码(Linq to SQL DataContext Lifetime Management)。它工作得很好,因为当前数据上下文存储在 HttpContext.Items 集合中。我知道我正在为每个 Web 请求重用相同的数据上下文。

但是,我一直无法在 WCF 服务中成功使用工厂。在非 HttpContext 应用程序上,工厂将数据上下文存储在线程数据槽中。

Thread.AllocateNamedDataSlot(key)

问题是,无论我如何在服务中设置 ConcurrencyMode 和 InstanceContextMode,每次调用都会重用线程,并重用相同的 dataContext。我不想要这个。我只希望每个服务方法调用存在一个数据上下文。有什么方法可以使用工厂来实现吗?我无法在每个客户端调用上找到任何唯一信息以用作我的数据上下文的标识符,因此它不会被其他请求重用......无论它是否是同一个客户端。

我想使用我的业务层而不是直接访问我的数据层,但恐怕我可能不得不在我的 WCF 服务中规定我自己的工作单元和数据上下文。有没有人在 WCF 服务中为他们的数据上下文使用某种工厂?我希望有一种方法让我的工厂知道它是否被 WCF 服务使用,然后唯一地处理数据上下文的存储

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);
}

然后在这里可以做些什么来实现我想要的?

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;
}
4

1 回答 1

0

我遇到了同样的问题。我使用 Castle.Windsor IOC 容器 +“PerWebRequest”生活方式,它的工作方式与您的工厂在引擎盖下的方式相似。

我仍在努力寻找满足我需求的完美解决方案,但我有一个可以帮助您的中间解决方案:让您的 WCF 服务使用 HttpContext 运行

1) 在您的 WCF 项目中,询问 ASP.Net 兼容性

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

2) 为您的服务添加一个属性来管理这种兼容性

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

来源:代码咆哮

于 2011-04-29T14:19:06.837 回答