Использовать состояние сеанса в запросах pLinq

У меня довольно простой запрос Linq (упрощенный код):

dim x = From Product In lstProductList.AsParallel 
        Order By Product.Price.GrossPrice Descending Select Product

Продукт - это класс. Product.Price — это дочерний класс, а GrossPrice — одно из его свойств. Чтобы определить цену, мне нужно использовать Session("exchange_rate").

Итак, для каждого элемента в lstProductList есть функция, которая делает следующее:

NetPrice=NetPrice * Session("exchange_rate")

(а затем GrossPrice возвращает NetPrice+VatAmount)

Независимо от того, что я пробовал, я не могу получить доступ к состоянию сеанса.

Я пробовал HttpContext.Current, но ничего не возвращает. Я пробовал реализовать IRequiresSessionState в классе (что помогает в аналогичной ситуации в общих обработчиках http [.ashx]) - не повезло.

Я использую простой режим состояния сеанса InProc. Курс обмена должен быть специфичным для пользователя.

Что я могу сделать?

Я работаю с: веб-разработкой, .Net 4, VB.net


Пошаговые инструкции:
page_load (в формате .aspx)
dim objSearch as new SearchClass()
dim output = objSearch.renderProductsFound()

затем в objSearch.renderProductsFound:
lstProductList.Add(objProduct(1))
...
lstProductList.Add(objProduct(n))

dim x = From Product In lstProductList.AsParallel
Упорядочить по Product.Price.GrossPrice По убыванию Выберите продукт

В Product.Price.GrossPrice Get:
return me.NetPrice+me.VatAmount

В Product.Price.NetPrice Get:
return NetBasePrice*Session("exchange_rate")

Опять же, упрощенный код, слишком много, чтобы вставлять его сюда. Работает нормально, если я разворачиваю запрос в циклы For.


person Dima    schedule 16.03.2010    source источник
comment
Вы действительно так пишете? Потому что вам нужно привести что-либо в сеансе к правильному типу перед его использованием.   -  person Jarrett Widman    schedule 16.03.2010
comment
нет, это просто упрощенно. Вычисление на самом деле намного сложнее, чем это, и есть много проверок для Nothing, преобразований типов (CDec в приведенном выше случае) и значений по умолчанию.   -  person Dima    schedule 16.03.2010
comment
Чтобы понять, доступен ли HttpContext, объясните, как вы вызываете этот код. Это из .aspx или что-то еще?   -  person Jarrett Widman    schedule 16.03.2010
comment
jarrett, я добавил цепочку событий в конец моего первоначального вопроса   -  person Dima    schedule 16.03.2010
comment
Вы можете Response.Write(Session("exchange_rate")) ?   -  person Nate    schedule 16.03.2010
comment
HttpContext.Current.Response.Write(HttpContext.Current.Session(exchange_rate)) генерирует исключение при помещении в свойство NetPrice или свойство GrossPrice (или в любое другое место, которое вызывается из приведенного выше запроса). Отладчик подтверждает, что HttpContext.Current ничего не возвращает. Response.Write(Session(exchange_rate)) вне запроса (например, page_load) возвращает то, что я установил. Для тестирования я использовал 1.2D   -  person Dima    schedule 18.03.2010


Ответы (2)


Я не совсем уверен, как работает HttpContext.Current, но я не удивлюсь, если он будет работать только в основном потоке, обрабатывающем HTTP-запрос. Это будет означать, что вы не можете использовать его в любых других потоках. Когда PLINQ выполняет запрос, он выбирает несколько случайных потоков из пула потоков и оценивает предикаты в запросе, используя эти потоки, так что это может быть причиной того, что ваш запрос не работает.

Если свойству GrossPrice требуется доступ только к одной вещи из состояния сеанса, должно быть довольно легко изменить его на метод и передать значение из состояния сеанса в качестве аргумента:

Dim rate = Session("exchange_rate")
Dim x = From product In lstProductList.AsParallel  
        Order By product.Price.GetGrossPrice(rate) Descending 
        Select product 

В зависимости от того, где вы позже будете использовать x, вы также можете добавить вызов ToList для принудительной оценки запроса (в противном случае он может выполняться лениво позже), но я думаю, что описанное выше изменение должно это исправить.

person Tomas Petricek    schedule 16.03.2010
comment
Томас, спасибо. Я думал в том же духе в отношении параллельных потоков, не имеющих доступа к HTTPContext и использующих локальные переменные, только мне нужно позже сериализовать этот класс в JSON, что не будет работать с методами. Лучшая идея, которая у меня есть на данный момент, состоит в том, чтобы иметь GrossPrice в качестве свойства и GetGrossPrice в качестве метода - используйте первый для сериализации и используйте последний в pLinq, должно быть более красноречивое решение для этого... - person Dima; 17.03.2010

Вы действительно должны считывать значения из состояния сеанса в локальные переменные, которые, как вы знаете, вам нужны в операторе LINQ. В противном случае вы фактически обращаетесь к экземпляру NameValueCollection каждый раз для каждого отдельного элемента в каждом отдельном потоке, когда значение по существу является постоянным.

person Drew Marsh    schedule 22.03.2010
comment
вы правы, я не думал об этом с этой стороны. Поскольку я использую plinq для получения максимальной производительности, на самом деле нет смысла использовать Session внутри запроса. - person Dima; 23.03.2010