Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么;LINQ表达式';x';无法翻译?I';我没有使用;其中();_C#_Linq_Entity Framework Core - Fatal编程技术网

C# 为什么;LINQ表达式';x';无法翻译?I';我没有使用;其中();

C# 为什么;LINQ表达式';x';无法翻译?I';我没有使用;其中();,c#,linq,entity-framework-core,C#,Linq,Entity Framework Core,当我执行以下代码时,我得到一个错误: System.InvalidOperationException:LINQ表达式'DbSet.Where(u=>u.NormalizedEmail==\u\u ToLower\u 0&& u、 无法翻译PasswordHash.SequenceEqual(_pass_1))' 但它在.NETCore2.2中运行良好。在.NET Core 3.1中出现错误 loginCreds.Password = loginCreds.Password.ToLower();

当我执行以下代码时,我得到一个错误:

System.InvalidOperationException:LINQ表达式'DbSet.Where(u=>u.NormalizedEmail==\u\u ToLower\u 0&& u、 无法翻译PasswordHash.SequenceEqual(_pass_1))'

但它在.NETCore2.2中运行良好。在.NET Core 3.1中出现错误

loginCreds.Password = loginCreds.Password.ToLower();
var pass = Helper.ComputeHash(loginCreds.Password);
var usr = await _context.Users
                        .FirstOrDefaultAsync(u => u.NormalizedEmail == loginCreds.Email
                                                  && u.PasswordHash.SequenceEqual(pass));
但是,当我将
u.PasswordHash.SequenceEqual(pass)
替换为
u.PasswordHash==新字节[16]
(仅用于测试)时,它可以工作。所以,问题在于
SequenceEqual(byte[]byte)
方法

我怎样才能解决这个问题


任何评论都将不胜感激。

在3.0之前,EF Core无法翻译的表达式将导致所有内容都被拉入客户端,然后在客户端进行过滤,这可能会变得非常缓慢。在3.0中,EF Core现在抛出一个异常,该异常的目标是开发人员优化他们的查询

因此,您的错误意味着EF Core无法将
u.PasswordHash.SequenceEqual(pass)
转换为SQL。您应该找到另一种方法来过滤查询


EF Core转换为SQL的方法有限(例如
string.StartsWith()
list.Contains()
)。

您可以在“受限客户端评估”中找到答案

例如,如果EF Core 2.2无法在 Where()调用时,它执行一个不带筛选器的SQL语句, 传输数据库中的所有行,然后对其进行筛选 记忆中

在EF Core 3.0中,我们将客户评估限制为仅在 顶层投影(本质上是对Select()的最后一次调用)。 当EF Core 3.0检测到无法在任何地方翻译的表达式时 否则在查询中,它会引发运行时异常

在EF Core 2.2中,带有
SequenceEqual
的查询部分实际上不是在SQL中完成的

您应该尝试这样做:

var usr = await _context.Users
.Where(u => u.NormalizedEmail == loginCreds.Email)
.ToListAsync()
.FirstOrDefault(u => u.PasswordHash.SequenceEqual(pass));

您说过它在
dotnetcore2.2
中工作,但在
dotnetcore3.1
中不工作。我假设这意味着您在
dotnetcore3.1
版本中也使用了
entityframeworkcore3
,看起来这是
entityframeworkcore3
中的一个突破性变化

旧行为

在3.0之前,当EF Core无法将作为查询一部分的表达式转换为SQL或参数时,它会自动在客户端计算表达式。默认情况下,对潜在昂贵表达式的客户端计算只会触发警告

新行为

从3.0开始,EF Core只允许在客户机上计算顶级投影(查询中的最后一个Select()调用)中的表达式。当查询的任何其他部分中的表达式无法转换为SQL或参数时,将引发异常

SequenceEqual
无法转换为SQL或参数,因此在版本
2.2
中,它会在客户端上自动执行该操作。现在在
3.1
版本中,它抛出了一个
invalidoOperationException
。使用相等运算符是可行的,因为它可以转换为SQL语句

为了修复它,为什么不选择“通过
电子邮件”
然后比较密码

loginCreds.Password = loginCreds.Password.ToLower();
var pass = Helper.ComputeHash(loginCreds.Password);
var usr = await _context.Users
    .FirstOrDefaultAsync(u =>u.NormalizedEmail == loginCreds.Email));
bool validUser = false;
if (usr != null)
{
    validUser = usr.PasswordHash.SequenceEquals(pass);
}
// if validUser is true, then the credentials were valid.

你的用户对象是什么样子的?“我如何解决这个问题?”你已经解决了。使用
=
而不是
SequenceEquals
。您的查询将被转换为SQL并执行。数据库不需要特殊的运算符来比较二进制数据。