为什么Select().Contains()可以,而Any()不可以?

huangapple go评论57阅读模式
英文:

Why is Select().Contains() ok while Any() is not?

问题

我首先尝试了以下代码:

var statesIndirectDelete = await States
	.Where(s => deletedCountries.Any(c => c.Id == s.CountryId))
	.ToListAsync();

这给我带来了以下错误:

System.InvalidOperationException
LINQ 表达式 'c => c.Id == EntityShaperExpression: 
    LouisHowe.core.Models.State
    ValueBufferExpression: 
        ProjectionBindingExpression: EmptyProjectionMember
    IsNullable: False
.CountryId' 无法被翻译。要么以可翻译的形式重写查询,要么明确切换到客户端评估,通过插入对 'AsEnumerable'、'AsAsyncEnumerable'、'ToList'  'ToListAsync' 的调用。有关更多信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2101038。

所以我随后将它更改为:

```csharp
var statesIndirectDelete = await States
	.Where(s => deletedCountries.Select(c => c.Id)
	.Contains(s.CountryId))
	.ToListAsync();

这个方法有效。但为什么第一个方法会失败呢?

而且,这个方法(Select.Contains)是否是以下任务的最佳方式:

  1. 我有一个 Country 对象的列表
  2. 我想从中获取所有与这些国家中的任何一个作为它们的上级的州对象列表。

换句话说,如果我的国家列表是 { "USA", "CANADA" },我想得到 "California"、"Quebec" 等,但我不想获取来自任何其他国家的州/省份。

英文:

I first tried the following code:

var statesIndirectDelete = await States
	.Where(s => deletedCountries.Any(c => c.Id == s.CountryId))
	.ToListAsync();

and that gave me the error:

System.InvalidOperationException
The LINQ expression 'c => c.Id == EntityShaperExpression: 
    LouisHowe.core.Models.State
    ValueBufferExpression: 
        ProjectionBindingExpression: EmptyProjectionMember
    IsNullable: False
.CountryId' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

so I then changed it to:

var statesIndirectDelete = await States
	.Where(s => deletedCountries.Select(c => c.Id)
	.Contains(s.CountryId))
	.ToListAsync();

and that works. But why does the first fail?

And is this (Select.Contains) the best way to:

  1. I have a list of Country objects
  2. From that I want to get a list of all State objects where they are all the states that have any of the countries as their parent.

In other words, if my country list is { "USA", "CANADA" } I want to get "California", "Quebec", ... but I do not want to get any states/provinces from any other country.

答案1

得分: 1

The Select().Contains() one simply translates to WHERE CountryID IN (逗号分隔的CountryIDs) because in this case you are just passing a collection of simple values.

With the Any() one, you are passing a list of complex objects to EF which cannot be easily translated to SQL like the above example.

英文:

The Select().Contains() one simply translates to WHERE CountryID IN (comma-separated CountryIDs) because in this case you are just passing a collection of simple values.

With the Any() one, you are passing a list of complex objects to EF which cannot be easily translated to SQL like the above example.

huangapple
  • 本文由 发表于 2023年6月5日 11:28:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/76403343.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定