ASP.NET Core - кеширование пользователей из Identity - PullRequest
0 голосов
/ 21 октября 2018

Я работаю со стандартной программой ASP.NET Core 2.1, и я рассматривал проблему, заключающуюся в том, что для многих моих методов контроллера требуется извлечение текущего зарегистрированного пользователя.

Iзаметил, что основной идентификационный код asp.net использует DBSet для хранения сущностей и что последующие обращения к нему должны выполнять чтение из локальных сущностей в памяти и не затрагивать БД, но, похоже, каждый раз, когда мой код требует чтения из БД(Я знаю, что я запускаю SQL Profiler и вижу, что запросы на выборку для AspNetUsers выполняются с использованием Id в качестве ключа)

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

Я установил хранилища EF и удостоверений по умолчанию в файле startup.cs ConfigureServices:

services.AddDbContext<MyDBContext>(options => options.UseSqlServer(Configuration.GetConnectionString("MyDBContext")));
services.AddIdentity<CustomIdentity, Models.Role>().AddDefaultTokenProviders().AddEntityFrameworkStores<MyDBContext>();

и прочитать пользователя в каждом методе контроллера:

var user = await _userManager.GetUserAsync(HttpContext.User);

в коде идентификации, кажется, что этот метод вызывает UserStore FindByIdAsync метод, который вызывает FindAsync в DBSet пользователей.в документе о производительности EF говорится:

It’s important to note that two different ObjectContext instances will have two different ObjectStateManager instances, meaning that they have separate object caches.

Итак, что здесь может пойти не так, какие-либо предположения, почему вызовы EF в ASP.NET Core в Userstore не используют локальный DBSet сущностей?Или я ошибаюсь - и каждый раз, когда вызывается контроллер, создается новый контекст EF?

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

какие-либо предложения, почему вызовы EF ASP.NET Core в Userstore не используют локальный DBSet объектов?

На самом деле, FindAsync делает .Цитирование msdn (выделено мной) ...

Асинхронно находит объект с заданными значениями первичного ключа. Если в контексте существует сущность с заданными значениями первичного ключа, то она сразу возвращается без отправки запроса в хранилище. В противном случае в хранилище делается запрос для сущности с данным первичным ключом.значения и этот объект, если он найден, присоединяется к контексту и возвращается.Если никакая сущность не найдена в контексте или хранилище, возвращается нуль.

Таким образом, вы не можете избежать первоначального чтения для каждого запроса объекта.Но последующие чтения в том же запросе не будут запрашивать хранилище.Это лучшее, что вы можете сделать вне сумасшедших уровней микрооптимизации

0 голосов
/ 22 октября 2018

Да.Контроллеры создаются и уничтожаются при каждом запросе, независимо от того, выполняет ли запрос тот же или другой пользователь.Кроме того, контекст ограничен запросом, поэтому он также создается и уничтожается при каждом запросе.Если вы запрашиваете одного и того же пользователя несколько раз во время одного и того же запроса, он попытается использовать кэш сущностей для последующих запросов, но вы, вероятно, этого не делаете.

Тем не менее, это пример из учебникапреждевременной оптимизации.Запрос пользователя из базы данных является чрезвычайно быстрым запросом.Это простой оператор выбора для первичного ключа - он не становится более быстрым и простым в отношении запросов к базе данных.Возможно, вам удастся сэкономить несколько миллисекунд, если вы используете кэширование памяти, но это связано с целым рядом соображений, особенно с осторожностью при выделении кеша пользователем, чтобы вы случайно не вводили неверные данные для неправильныхпользователь.Более того, кэш-память проблематична по целому ряду причин, поэтому более распространено использование распределенного кеширования в производстве.Когда вы перейдете туда, кеширование на самом деле ничего не даст вам для простого запроса, подобного этому, потому что вы просто извлекаете его из хранилища распределенного кэша (которое может быть даже базой данных, такой как SQL Server), а не из вашей базы данных.Имеет смысл только кэшировать сложные и / или медленные запросы, поскольку только тогда извлечение его из кэша на самом деле оказывается быстрее, чем просто повторное попадание в базу данных.

Длинно и коротко, не бойтесьзапросить базу данных.Вот для чего это.Это ваш источник данных, поэтому, если вам нужны данные, сделайте запрос.После того, как ваш сайт работает, вы можете профилировать или иным образом отслеживать производительность, и если вы заметите медленные или чрезмерные запросы, , а затем , вы можете начать искать способы оптимизации.Не беспокойтесь, пока это не станет проблемой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...