【发布时间】:2019-03-25 18:41:48
【问题描述】:
我正在使用标准的 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);
在身份代码中,该方法似乎调用了 UserStore FindByIdAsync 方法,该方法调用了用户 DBSet 上的 FindAsync。
EF performance paper 说:
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 上下文?
【问题讨论】:
-
ef dbcontext 默认为作用域生命周期,这意味着它会在每个请求结束时自动释放。您不应该尝试将其保留更长时间。为什么需要这么多从数据库中获取用户?诸如用户电子邮件、ID、姓名和角色之类的东西可以是被序列化并持久化到 auth cookie 中的声明,所以如果你只需要这些东西,你就不需要经常为用户访问数据库。您可以访问 HttpContext.User,它是由 auth 中间件自动从 auth cookie 反序列化的声明主体。
-
@JoeAudette 我很害怕,为什么还要在 Usermanager 中读取明确的 DBset!我需要与用户一起存储的各种属性,将它们全部转换为声明并不正确。
-
如果您认为您需要访问的内容不适合声明,那么您可以将它们缓存在内存或会话状态中,以避免在每次请求时都访问数据库。所有事情都需要权衡。在不具体了解您需要哪些数据的情况下,我无法就其中的部分或全部是否适合作为声明提出任何建议。
-
@JoeAudette 只是与用户关联的自定义数据,它们确实需要被缓存,我希望将它们与用户放在一起会更容易,因为我们有一个 usermanager 对象而不是通常的 EF 调用.我将不得不为这些想出一个缓存机制。
标签: asp.net-core asp.net-identity entity-framework-core