ASP.NET Core-从身份缓存用户

时间:2018-10-21 15:00:39

标签: asp.net-core asp.net-identity entity-framework-core

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

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

我知道设置身份的方法有很多,并且在版本上进行了更改,也许我做的不正确,或者这里是否存在可以解决的基本问题。

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

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上调用了FindAsyncEF 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.

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

2 个答案:

答案 0 :(得分:1)

  

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

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

  

异步找到具有给定主键值的实体。 如果上下文中存在具有给定主键值的实体,则将其立即返回而无需向商店提出请求。否则,将向商店发出具有给定主键值的实体的请求。键值和该实体(如果找到)将附加到上下文并返回。如果在上下文或商店中未找到任何实体,则返回null。

因此,您不能避免对对象的每次请求都进行初始读取。但是在同一请求中的后续读取将不会查询商店。在疯狂的微优化水平之外,这是最好的选择

答案 1 :(得分:0)

是的。每次请求都将实例化并销毁控制器,而不管发出请求的用户是相同还是不同。此外,上下文是请求范围的,因此也随每个请求实例化和销毁它。如果您在同一请求中多次查询同一用户,它将尝试使用实体缓存进行后续查询,但您可能不会这样做。

也就是说,这是过早优化的教科书示例。从数据库中查询用户是非常快速的查询。这只是主键上的简单选择语句-就数据库查询而言,它不会变得更加快捷或简单。如果您使用内存缓存,您也许可以节省几毫秒,但这带有一整套注意事项,尤其是要小心地按用户隔离缓存,以免您不小心为错误的数据带来了错误的数据。用户。更重要的是,由于多种原因,内存缓存存在问题,因此在生产中使用分布式缓存更为典型。一旦到达那里,对于像这样的简单查询,缓存实际上并不会为您带来任何好处,因为您只是从分布式缓存存储(甚至可能是SQL Server这样的数据库)中获取数据,而不是从数据库中获取。仅对复杂和/或慢速查询进行缓存才有意义,因为只有这样,从缓存中检索它实际上比再次击中数据库要快得多。

又长又短,不要害怕查询数据库。那就是它的目的。它是数据的来源,因此,如果需要数据,请进行查询。一旦您访问了网站,就可以进行性能分析或以其他方式对其进行监视,如果发现查询缓慢或过多,则可以然后开始寻找优化方法。直到它真正成为问题之前,不要担心。