需要检索包含与另一个列表匹配的子项目的项目列表

Ber*_*nDK 3 c# linq collections linq-to-sql

情况:

我有一些具有某些技能的人,他们可以/可能属于多个领域。技能链接在单独的表格中,区域也是如此。

我通过选择所有与每个技能匹配的人来获取人员列表,并将他们添加到我可以使用 Distinct() 的列表中,以确保他们不会出现两次。

结果人员名单:

List<Person> peopleWithRightSkills
Run Code Online (Sandbox Code Playgroud)

在每个 [Person] 对象上,我至少链接了 1 个地址,但与 [Person] 相关联的地址可以有更多

我还有另一个清单:

List<PostalCode> acceptedPostalcodes
Run Code Online (Sandbox Code Playgroud)

现在我需要比较和过滤那些拥有地址邮政编码在可接受邮政编码范围内的 peopleWithRightSkills

我一直在研究 Lambda 表达式、SelectMany 以及其他解决方案,但现在,我只有一个选择,我认为这是做事的“旧风格”,即遍历每个 Person 并为每个人匹配她/他的地址列表对照邮政编码列表。对于每场比赛,然后将其添加到:

List<Person> matchedPeople
Run Code Online (Sandbox Code Playgroud)

表格概览(缩短所需的详细信息)

[Table:Person]
int:ID (primary)
string:FirstName
string:LastName

[Table:Address]
int:Person_ID (foreign key to Person)
int:PostalCode_ID (foreing key to PostalCode)
string:StreetName

[Table:PostalCode]
int:ID
string:CityName
Run Code Online (Sandbox Code Playgroud)

正如我所看到的问题,它只是一个“公关人员短名单”(最少 1 个,也许最多 10 个地址),我需要将此地址列表与每个人的“有效邮政编码列表”进行比较。

希望对此有一个很好的答案,因为我已经被困了几个小时了,试图找出使用什么语法来解决这个更漂亮但性能更难的问题。

Amy*_*y B 5

List<int> peopleIDs = peopleWithRightSkills.Select(p => p.ID).ToList();
List<int> postalIDs = acceptedPostalCodes.Select(c => c.ID).ToList();

var query = db.Persons
  .Where(p => peopleIDs.Contains(p.ID)
  .Where(p => p.Addresses.Any(a => postalIDs.Contains(a.PostalCode_ID))
  );
Run Code Online (Sandbox Code Playgroud)

LinqToSql 会将 中的每个元素转换List<int>为参数。然后它将Contains方法调用转换为 TSqlIN子句。

请注意,LinqToSql 会很乐意将尽可能多的元素转换为参数(我自己见过 50k),但是SqlServer 只接受 ~2000 个参数。如果您的列表包含的元素多于您需要分解这些列表的元素。如果您有 1500 名具有正确技能的人员和 1000 个已接受的邮政编码,则您需要向 SQL Server 发送 2500 个参数,这是 400 个太多,并且会给您一个 SqlException。