我们正在使用Asp。Oracle数据库上的Net Identity 2.2.1和EF 6.1.3版本。
我们确实在UPPER(USERNAME)上的用户表上有一个索引,但是对于每个用户登录,我们仍然对用户表进行全表扫描。
这个问题似乎是由UserStore中的代码引起的:
public virtual Task<TUser> FindByNameAsync(string userName)
{
this.ThrowIfDisposed();
return this.GetUserAggregateAsync((
Expression<Func<TUser, bool>>) (u =>
u.UserName.ToUpper() == userName.ToUpper()));
}
将生成带有
的SQLWHERE (((UPPER("Extent1".USERNAME)) = :p__linq__0)
OR ((UPPER("Extent1".USERNAME) IS NULL) AND
(:p__linq__0 IS NULL)))
和OR部分似乎使优化器选择全表扫描。
当使用SQL Server时,可以将where语句修改为:
public virtual Task<TUser> FindByNameAsync(string userName)
{
this.ThrowIfDisposed();
var uName = userName.ToUpper();
return this.GetUserAggregateAsync((
Expression<Func<TUser, bool>>) (u =>
u.UserName.ToUpper() == uName));
}
和where部分现在是:
WHERE N'<USERNAME>' = (UPPER([Extent1].[USERNAME]))
但是我失去了如何在使用Oracle时优化这个选项。我试过两种Oracle。管理司机和司机。当在字段上使用UPPER函数时,它们都生成带有OR的where语句。
数据库中需要有大小写不敏感的用户名。
那么,当我们使用UPPER(field) =某些东西时,为什么EF生成一个带有OR语句的SQL ?
还有别的办法吗?有人有好的解决方案吗?
此时,我们的最后一个选择可能是将数据表中的用户名设置为UPPERCASE,从而避免使用UPPER函数——但这似乎不是最佳解决方案。有没有试过设置
context.UseDatabaseNullSemantics = true;
https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbcontextconfiguration.usedatabasenullsemantics (v = vs.113) . aspx