asp.net - System.Web.Providers.DefaultMembershipProvider 有性能问题/死锁

标签 asp.net asp.net-membership membership-provider

我们已经开始使用 NuGet 的 Microsoft.AspNet.Providers.Core 包中提供的更新的 System.Web.Providers。我们开始迁移现有用户,发现性能下降,然后出现死锁。这是少于 30,000 个用户(远少于我们需要创建的 1,000,000+)。当我们调用提供程序时,它来自每个服务器上的多个线程,并且有多个服务器运行相同的进程。这是为了能够尽快创建我们需要的所有用户,并模拟我们希望在上线时看到的负载。

SQL Server 为死锁生成的日志包含以下 EF 生成的 sql:

SELECT
    [Limit1].[UserId] AS [UserId]
  , [Limit1].[ApplicationId] AS [ApplicationId]
  , [Limit1].[UserName] AS [UserName]
  , [Limit1].[IsAnonymous] AS [IsAnonymous]
  , [Limit1].[LastActivityDate] AS [LastActivityDate]
FROM
    (SELECT TOP (1)
        [Extent1].[UserId] AS [UserId]
      , [Extent1].[ApplicationId] AS [ApplicationId]
      , [Extent1].[UserName] AS [UserName]
      , [Extent1].[IsAnonymous] AS [IsAnonymous]
      , [Extent1].[LastActivityDate] AS [LastActivityDate]
     FROM
        [dbo].[Users] AS [Extent1]
        INNER JOIN [dbo].[Applications] AS [Extent2] ON [Extent1].[ApplicationId] = [Extent2].[ApplicationId]
     WHERE
        ((LOWER([Extent2].[ApplicationName])) = (LOWER(@p__linq__0)))
        AND ((LOWER([Extent1].[UserName])) = (LOWER(@p__linq__1)))
    ) AS [Limit1]

我们手动运行查询,执行计划说它正在执行表扫描,即使有底层索引。这样做的原因是使用了 LOWER([Extent1].[UserName]) .

我们查看了提供者代码,看看我们是否做错了什么,或者是否有办法拦截或替换数据库访问代码。我们没有看到任何选项可以做到这一点,但我们确实找到了 LOWER 的来源。问题,.ToLower()在列和参数上都被调用。
return (from u in ctx.Users
    join a in ctx.Applications on u.ApplicationId equals a.ApplicationId into a
    where (a.ApplicationName.ToLower() == applicationName.ToLower()) && (u.UserName.ToLower() == userName.ToLower())
    select u).FirstOrDefault<User>();

有谁知道我们将提供者的行为更改为不使用 .ToLower() 从而允许使用索引的方法?

最佳答案

您可以根据 Sql Server : Lower function on Indexed Column 在较低(用户名)上创建索引

ALTER TABLE dbo.users ADD LowerFieldName AS LOWER(username) PERSISTED
CREATE NONCLUSTERED INDEX IX_users_LowerFieldName_  ON dbo.users(LowerFieldName)

关于asp.net - System.Web.Providers.DefaultMembershipProvider 有性能问题/死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15977369/

相关文章:

c# - 静态字段与 session 变量

asp.net - 为什么 ASP.NET MVC 3 无法正确验证我的 float ?

c# - Membership.GetUser(username) - 如何返回正确的大小写?

asp.net - 我可以同时使用多个 MembershipProvider 吗?

asp.net-mvc-3 - ASP.NET MVC 3 Ninject 自定义成员资格和角色提供程序

asp.net - 如何获取默认的 asp.net 成员资格提供商名称?

asp.net - 无法在 mono/linux 上运行 kestrel

.net - 如何在生产中管理 ASP.NET SQL 成员角色/用户?

c# - Web 应用程序中的安全方法

c# - xamarin android 应用程序 : how to get the Resources folder of my project