Я создал класс реестра в .NET, который является одноэлементным. Очевидно, этот синглтон ведет себя так, как если бы он хранился в кэше (объект синглтона доступен для каждого сеанса). Это хорошая практика: следует ли мне добавлять этот синглтон в кеш? + нужно ли мне устранять проблемы параллелизма с функцией GetInstance ()?
namespace Edu3.Business.Registry
{
public class ExamDTORegistry
{
private static ExamDTORegistry instance;
private Dictionary<int, ExamDTO> examDTODictionary;
private ExamDTORegistry()
{
examDTODictionary = new Dictionary<int, ExamDTO>();
}
public static ExamDTORegistry GetInstance()
{
if (instance == null)
{
instance = new ExamDTORegistry();
}
return instance;
}
}
}





Что ж, ваш метод GetInstance определенно не является потокобезопасным - если два потока вызывают его одновременно, они вполне могут получить два разных экземпляра. У меня есть страница о реализации одноэлементного паттерна, если это поможет.
Ваш код полагаться является одноэлементным? Имейте в виду, что если домен приложения перезагружен, вы все равно получите новый экземпляр.
Однако я не вижу особой пользы от помещения объекта в кеш. Есть ли что-нибудь, о чем вы думаете конкретно?
Несмотря на их присутствие в GoF синглтоны обычно считаются плохая практика. Есть ли причина, по которой вы хотите иметь только один экземпляр?
Это хорошая практика при использовании в правильном месте. К сожалению, я НИКОГДА не работал в месте, которое действительно является нужный, хотя я видел их реализованные сотни раз :) MonoState - хорошая альтернатива.
Чтобы ответить на ваш вопрос, у меня 200 кандидатов одновременно запрашивают один и тот же ExamDTO (по идентификатору). Я видел, что код на стороне сервера 200 раз заходил в базу данных для сдачи экзамена. Теперь я хотел кэшировать экзамен по его идентификатору, чтобы после загрузки сервер не переходил в базу данных снова.
Тогда вам нужен кеш (ни одного сингла, перепутать их опасно). Для одного предложения см. Комментарий Бена к MonoState. В противном случае скройте кеширование в вашем слое данных. Хорошие картографы O / R, такие как NHibernate, уже поддерживают подобные вещи.
Другой вопрос (извините за любопытство): это вызывает у вас проблемы с производительностью? Вы будете удивлены, но 200 запросов на одну и ту же запись - это легкий ветерок для большинства современных dbs. Если у вас возникла проблема с перфомансом, я полностью понимаю необходимость кеширования.
Я буду честен с вами, я старший специалист по гибкости, уже полтора года пытаюсь изучить ASP.NET. На самом деле это 200 запросов к хранимой процедуре, что довольно интенсивно. Если бы я сделал это с помощью NHibernate или SubSonic, в одном запросе потребовалось бы адресовать пару записей.
В чем разница между кешем и синглтоном? Поведение выглядит одинаково ... Синглтон можно вызывать из любого сеанса (это как глобальная переменная).
Я посмотрел на MonoState, и разве Singleton не является чем-то вроде MonoState с одной статической переменной, самим экземпляром?
Синглтон предназначен для ограничения класса только одним экземпляром с глобальным доступом. Шаблон моносостояния - это способ, которым несколько экземпляров имеют общее состояние. Кэш предоставляет доступ к одному и тому же объекту несколько раз без создания их новых экземпляров. MonoState - это ОДИН способ реализации кеша.
«Синглтон может быть вызван из любого сеанса (это как глобальная переменная)» И глобальные переменные ПЛОХО и НЕ являются правильным использованием шаблона синглтона.
Не уверен, что вы имеете в виду под кешем ... если вы хотите, чтобы это было кешировано (например, ... храните его в памяти, чтобы вам не приходилось снова извлекать его из какого-либо хранилища данных), тогда да, вы можете поместить его в кеш, и он будет глобальным для всех пользователей. Сеанс означает каждого пользователя, поэтому я не думаю, что это то, что вам нужно.
HttpContext.Cache доступен для всех сеансов, но элементы в кеше могут быть удалены из памяти по истечении срока их действия или при нехватке памяти.
HttpContext.Application также доступен для всех сеансов и является хорошим местом для хранения постоянных объектов всего приложения.
Поскольку вы уже создали синглтон, и он работает, я не понимаю, почему вместо этого следует использовать одну из встроенных коллекций синглтонов, если вам не нужны дополнительные функции, которые дает вам Cache.
Что это за дополнительные функции?
Истечение срока действия / удаление элементов из памяти.
я бы сделал это так:
частный статический экземпляр ExamDTORegistry ТОЛЬКО ДЛЯ ЧТЕНИЯ;
тогда вам не нужно проверять NULL и его потокобезопасность.
Я думаю, что исходный вопрос говорил о том, что было предпочтительнее. Если у вас есть данные, которые остаются статическими или практически неизменяемыми, тогда имеет смысл использовать http-кеширование или одноэлементный шаблон. Если синглтон загружается при запуске приложения, тогда вообще нет проблемы с потоком. Как только синглтон будет установлен, вы получите тот же экземпляр, который вы запрашивали. Проблема со многими из того, что я вижу в реальных реализациях, заключается в том, что люди используют оба, даже не задумываясь над этим. Почему вы должны истекать неизменяемые данные конфигурации? Был один клиент, который кэшировал данные и все еще создавал объекты ADO DB и т. д., Когда они в последний раз проверяли, находится ли он в кеше. По сути, оба этих решения будут работать для вас, но чтобы получить какой-либо положительный эффект, убедитесь, что вы используете cache / singleton. В любом случае, если ваши данные недоступны, оба должны быть обновлены в этот момент.
Да, когда AppDomain перезагружается, с новым экземпляром проблем не возникает. Но синглтон ведет себя как глобальный объект, не так ли? При тестировании я вижу, что ASP.NET не создает синглтон для каждого сеанса, а только синглтон для всего приложения.