Resharper说要把foreach转换成LINQ,但这可能吗?
本文关键字:LINQ foreach 转换 Resharper | 更新日期: 2023-09-27 18:03:23
我有一个Project实体,它有一个导航属性,它是一个地址列表。在搜索页面上,我允许用户一次按多个地址搜索项目。是否可以在单个语句中做到这一点,或者我需要循环遍历搜索的地址?
目前我有以下代码,其中searchedAddresses是用于搜索项目的地址列表。在foreach循环中,我创建了一个查询,并在每次循环中将其与整个查询联合起来。Resharper说foreach可以用LINQ重写,如果可能的话,我想摆脱查询的联合。
foreach (AddressModel address in searchedAddresses)
{
var query = _projectRepository.Get().Where(p => p.Addresses.Any(a => a.StreetName.ToLower().StartsWith(address.StreetName.ToLower())));
union = (union == null ? query : union.Union(query));
}
我试着把它写成一个语句,但它不起作用:
var query = _projectRepository.Get().Where(p => p.Addresses.Any(a => searchedAddresses.Any(sa => a.StreetName.ToLower().StartsWith(sa.StreetName.ToLower())));
当我这样做的时候,我得到以下错误:"无法创建类型' epec . webapi . models . addressmodel '的常量值。在此上下文中只支持基本类型或枚举类型。"
我假设这是因为searchedAddresses.Any()部分。有人知道如何编写这个查询,以便我不需要遍历地址和联合查询吗?或者这是一件可以做的事情?
谢谢!
编辑:在我最初忘记的第二个查询中添加了ToLower和StartsWith。
我想最简单的方法是为您首先搜索的街道名称创建一个List<string>
-我希望这些名称是可转换的:
var searchedStreets = searchedAddresses.Select(x => x.StreetName).ToList();
var query = projectRepository
.Get()
.Where(p => p.Addresses.Any(a => searchStreets.Contains(a.StreetName)));
如果List<string>
不起作用,可能值得尝试string[]
。(把ToList
改成ToArray
)
我怀疑ReSharper想让你做这样的事情:
var union = searchedAddresses
.Select(address => _projectRepository.Get()
.Where(p => p.Addresses.Any(a =>
a.StreetName.ToLower().StartsWith(address.StreetName.ToLower()))))
.Aggregate(
(something)null,
(union, query) => union.Union(query));
在原始代码中something
与union
类型相同。
(如果它告诉你可以将循环转换为单个查询,它应该也会给你自动执行的选项)
我不认为这是特别干净的。
当您必须像这样"合并"给定集合的所有结果时,您可以用SelectMany语句替换Foreach语句;
searchedAddresses
.SelectMany(address =>
_projectRepository
.Get()
.Where(p => p.Addresses.Any(a =>
a.StreetName
.ToLower()
.StartsWith(address.StreetName.ToLower()))))
.Distinct();
这将遍历每个结果,与合并每个子查询
产生相同的效果(可能会提高性能)编辑:当我复制/粘贴你的问题代码时,使用了错误的lambda参数。固定。编辑:与Union不同,SelectMany不删除重复项,因此我相应地更新了代码