首页 > 解决方案 > ASP.NET Core - 从身份缓存用户

问题描述

我正在使用标准的 ASP.NET Core 2.1 程序,并且我一直在考虑这样一个问题,即我的许多控制器方法都需要检索当前登录的用户。

我注意到 asp.net 核心身份代码使用 DBSet 来保存实体,并且对它的后续调用应该从内存中的本地实体读取而不是访问数据库,但似乎每次我的代码都需要一个数据库阅读(我知道我正在运行 SQL Profiler,并看到针对 AspNetUsers 的选择查询正在使用 Id 作为键运行)

我知道有很多方法可以设置 Identity,并且它改变了版本,可能我没有做正确的事情,或者这里有一个可以解决的基本问题。

我在 startup.cs 的 ConfigureServices 中设置了默认的 EF 和 Identity 存储:

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

并在每个控制器方法中读取用户:

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

在身份代码中,该方法似乎调用了调用用户 DBSet 的 UserStoreFindByIdAsync方法FindAsyncEF 性能文件说:

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

那么这里可能出了什么问题,为什么 ASP.NET Core 在 Userstore 中的 EF 调用没有使用本地实体 DBSet 的任何建议?还是我想错了 - 每次调用控制器时,都会创建一个新的 EF 上下文?

标签: asp.net-coreasp.net-identityentity-framework-core

解决方案


为什么 ASP.NET Core 在 Userstore 中的 EF 调用不使用本地实体 DBSet 有什么建议吗?

实际上,确实这样做。引用 msdn(强调我的)...FindAsync

异步查找具有给定主键值的实体。如果上下文中存在具有给定主键值的实体,则立即返回它而不向存储区发出请求。否则,将向存储请求具有给定主键值的实体,如果找到该实体,则将其附加到上下文并返回。如果在上下文或存储中未找到实体,则返回 null。

因此,您无法避免对对象的每个请求的初始读取。但是同一请求中的后续读取不会查询存储。这是你在疯狂的微优化水平之外所能做的最好的事情


推荐阅读