2016-11-20 67 views
0

我得到了这个查询,在生产环境中非常慢。我想知道为什么以及是否有更好的方法来达到同样的结果。为什么我的linq到SQL查询很慢?

public async Task<Membership> FindByEmailByAccessL1OrL3OrL4Async(string email) 
{ 
    return await (from m in this.Queryable() 
        where m.Email == email 
         && (m.RoleMemberships.Select(r => r.RoleId).Contains(RoleConstants.ACCESSGRANTEDL1ID) 
          || m.RoleMemberships.Select(r => r.RoleId).Contains(RoleConstants.ACCESSGRANTEDL3ID) 
          || m.RoleMemberships.Select(r => r.RoleId).Contains(RoleConstants.ACCESSGRANTEDL4ID)) 
        select m).SingleOrDefaultAsync(); 
} 

简而言之,此查询的目的是通过电子邮件获取用户成员资格并继续登录。我有更多的用户会员资格,这个查询会更慢。

谢谢

大卫

编辑

this.Queryable()是做select * from Memberships的等价物。 Membership表有许多角色,并且角色有许多成员。

此外,成员资格表最多需要12秒才能获取240行的登录信息。我必须按角色过滤,因为系统中的电子邮件值不是唯一的。只有一些角色才能访问登录,并且这些角色将拥有唯一的电子邮件。这就是为什么我必须过滤。此查询返回一个成员资格以继续进行登录,该查询通过上面的查询进行选择。所以没有IQueryableIEnumerableList,只是SingleOrDefault值。

+0

'this.Queryable()'???你不提供太多的信息.​​.什么是“这个”? Queryable()方法返回什么?显示该代码? – user3185569

+0

对不起!代码位于存储库架构内。我在编辑部分提供了更多信息。 –

+0

我们可能需要查看SQL表定义以及任何索引。 – RBarryYoung

回答

3

我想生成的查询是非常糟糕的,因为你做同样的事情多次是:

m.RoleMemberships.Select(r => r.RoleId) 

相反,你可以使用一次做到这一点:

public Task<Membership> FindByEmailByAccessL1OrL3OrL4Async(string email) 
{ 
    return (from m in this.Queryable() 
      where m.Email == email 
       && (m.RoleMemberships.Any(
        r => r.RoleId == RoleConstants.ACCESSGRANTEDL1ID 
         || r.RoleID == RoleConstants.ACCESSGRANTEDL3ID 
         || r.RoleID == RoleConstants.ACCESSGRANTEDL4ID) 
      select m).SingleOrDefaultAsync(); 
} 

的上面会让事情变得更好,我猜。您可以使用调试器在两种情况下检查生成的查询。

另外请注意,您不需要等待结果,只需返回任务,调用者需要等待它。

+0

“是非常乐队” - 你的意思是“坏”,“宽”还是其他? –

+0

@MarkSchultheiss错字修正。感谢您指出了这一点。 – user3185569

0

我认为有很多数据需要加载,EF是非常缓慢的映射技术,它会创建有趣的查询(你可以看到这个here)。你是否有性能问题?也许你应该选择其他映射技术(stacks dapper例如Dapper)。当我们进行测试时,速度比EF快两倍。

+0

你如何推断​​EF在这里玩? –

+0

再一次,如果我们有大量的数据,它不是很快,这就是为什么我认为这是这种情况 –