2010-04-27 4 views
4

У меня есть обработчик (например, list.ashx), который имеет метод, который извлекает большой набор данных, а затем захватывает только записи, которые будут отображаться на любой заданной «странице» данных. Мы разрешаем пользователям выполнять сортировку по этим результатам. Таким образом, при любом запуске страницы я буду извлекать набор данных, который я получил всего несколько секунд/минут назад, но переупорядочивая их или показывая следующую страницу данных и т. Д.Viewstate в обработчике .ashx?

Я хочу сказать, что мой набор данных действительно не изменилось. Обычно набор данных застревает в представлении страницы, но поскольку я использую обработчик, у меня нет такого удобства. По крайней мере, я так не думаю.

Итак, что является распространенным способом хранения виджета, связанного с текущей страницей данного пользователя при использовании обработчика? Есть ли способ взять набор данных, каким-то образом закодировать его и отправить обратно пользователю, а затем на следующий вызов, передать его обратно и затем перевести набор данных из этих бит?

Я не думаю, что сеанс будет хорошим местом для его хранения, так как у нас может быть 1000 пользователей, которые просматривают разные наборы данных разных данных, и это может привести к тому, что сервер окажется на коленях. По крайней мере, я так думаю.

Есть ли у кого-нибудь опыт в подобной ситуации, и можете ли вы дать мне какие-либо советы?

ответ

3

В этой ситуации я бы использовал кеш с некоторым типом информации о пользователе и запросе в качестве ключа. Причина в том, что вы говорите, что это большой набор данных. Прямо есть то, что вы не хотите постоянно поднимать и опускать по трубе. Помните, что ваш сервер все еще должен получать данные, если он находится в ViewState и обрабатывает его. Я хотел бы сделать что-то вроде этого, которое будет кэшировать его для конкретного пользователя и имеет короткое действие:

public DataSet GetSomeData(string user, string query, string sort) 
{ 
    // You could make the key just based on the query params but figured 
    // you would want the user in there as well. 
    // You could user just the user if you want to limit it to one cached item 
    // per user too. 
    string key = string.Format("{0}:{1}", user, query); 

    DataSet ds = HttpContext.Current.Cache[key] as DataSet; 
    if (ds == null) 
    { 
     // Need to reload or get the data 
     ds = LoadMyData(query); 

     // Now store it and make the expiry short so it doesn't bog up your server 
     // needlessly... worst case you have to retrieve it again because the data 
     // has expired. 
     HttpContext.Current.Cache.Insert(key, ds, null, 
      DateTime.UtcNow.AddMinutes(yourTimeout), 
      System.Web.Caching.Cache.NoSlidingExpiration); 
    } 

    // Perform the sort or leave as default sorting and return 
    return (string.IsNullOrEmpty(sort) ? ds : sortSortMyDataSet(ds, sort)); 
} 

Когда вы говорите 1000-х пользователи, что значит ли одновременно работающие пользователь? Если ваше время истечения составляет 1 минуту, сколько одновременных пользователей совершит этот вызов за минуту и ​​потребует сортировки. Я думаю, что разгрузка данных на что-то вроде ViewState - это просто торговля некоторой кэш-памятью для пропускной способности и обработка больших запросов запросов туда и обратно. Чем меньше вы должны передавать назад и вперед, тем лучше, на мой взгляд.

+0

Прямо сейчас, возможно, всего 100 одновременных пользователей. В ближайшие несколько месяцев мы достигнем 1000. Мне нравится идея таймаута для кэширования. Можно ли точно узнать, освобождает ли IIS кеш во времени? Я имею в виду, есть ли какие-то настройки в IIS, которые мне нужно активировать, чтобы отключить тайм-ауты кэшей? Я не хочу использовать этот код, а затем узнаю, что IIS игнорирует тайм-аут. Я предполагаю, что тестирование с 1 минутой и проверка нулевого значения выберет это. Спасибо за ответ - это именно тот компромисс, который мне нужен. –

1

Лучшее, что вы можете сделать, это «вырастить свой собственный», включив в обработчик ASHX сериализованный набор данных в теле запроса. Затем ваш обработчик проверяет, действительно ли у запроса есть тело, проверив Request.ContentLength, а затем прочитав от Request.InputStream, и если он сериализует это тело обратно в набор данных вместо чтения из вашей базы данных.

2

Почему вы не используете кеширование на стороне сервера?

A Я понимаю, вы извлекаете большой объем данных, а затем возвращаете только нужные записи из этих данных для разных клиентов. Таким образом, вы можете использовать для этого свойство HttpContext.Current.Cache.

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

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

+0

Спасибо за ответ, Алекс.Это хорошее описание того, что опубликовал Kelsey. Я выбрал Келси как принятый ответ только потому, что они тоже дали такой хороший пример кода. Тем не менее, я действительно ценю несколько областей подтверждения. –