Я использовал код DataContextFactory Рика Страла (Linq to SQL DataContext Lifetime Management). на уровне данных, используемом приложением ASP.Net. Это прекрасно работает, потому что текущий контекст данных хранится в коллекции HttpContext.Items. Я знаю, что повторно использую один и тот же контекст данных для каждого веб-запроса.
Однако мне не удалось успешно использовать фабрику в службе 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;
}
1 ответ
У меня та же проблема. Я использую контейнер 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
{
...
}
Источник : разбор кода
Похожие вопросы
Новые вопросы
linq-to-sql
Этот тег НЕ О ПЕРЕВОДЕ LINQ TO SQL! Linq to SQL — это старая ORM, которая является частью .Net framework, а не ядром. При возникновении вопросов о преобразовании LINQ в SQL используйте тег соответствующего ORM.