更高效的Linq to SQL

4
我一直在使用Linq to SQL帮助我搜索简单的数据库。该数据库由两个表Player和Team组成,每个球员记录都有一个Team Id来链接(Player.TeamId -> Team.Id)这两个表。
为了增加一些复杂性,Team表包含过去10个赛季的历史数据。这意味着每个Team可能在Team表中具有高达10个不同的记录,与所代表的10个赛季相关。
我的查询要做的是搜索符合搜索条件的球员并返回该团队的每个返回球员的队友列表,以及当时的季节。
搜索条件包括名字,姓氏,季节列表和团队名称。
我的查询如下:
using (var context = DataContextFactory.Context)
{
var playerList = context.GetTable<Player>(t =>  searchRequest.Seasons.Contains((int) t.Team.Season))
                              .Where(p => string.Equals(p.Surname, (searchRequest.Surname ?? p.Surname), StringComparison.OrdinalIgnoreCase) &&
                                          string.Equals(p.Forename, (searchRequest.Forename ?? p.Forename), StringComparison.OrdinalIgnoreCase) &&
                                          string.Equals(p.Team.Name, (searchRequest.TeamName ?? p.Team.Name), StringComparison.OrdinalIgnoreCase)
                                    )).ToList();

var teamMateList = new List<Player>();

foreach (var Player in playerList.Select(p => context.GetTable<Player>(
                              tm => tm.Team.Id == p.Team.Id && tm.Id.CompareTo(p.Id) != 0)))
{
    otherPeopleList.AddRange(people);
}
}

这个代码可以返回符合搜索条件的球员列表(playerList),并且对于这些球员,我可以从第二个查询结果(teamMateList)中映射他们的队友。

我的问题是Linq to SQL将其转换为相当低效的SQL。第一个问题是它从数据库中选择了整个Player表 - 我假设这是因为Linq to SQL无法将我的Where子句转换为标准SQL,因此返回整个表并在代码中执行Where部分的查询?

第二个问题是,在进行第二个查询时,Linq to SQL为playerList的每个成员生成单独的查询。阅读代码时,这可能是有道理的,但我认为Linq应该足够聪明,将其转换为单个查询以实现更高效的搜索。

您对如何简化我的查询有什么想法/建议吗?


2
如果只使用 == 而不是 StringComparison.OrdinalIgnoreCase,并让数据库处理校对,情况是否会有所改善? - Dervall
@Dervall 没关系。排序将仅由服务器处理 - Oybek
1
@Oybek 噢,数据库不在意,但我不确定 Linq to SQL 是否能够正确地将比较翻译成 SQL。 - Dervall
2个回答

1
我猜测这是因为 Linq to SQL 无法将我的 Where 子句转换为标准 SQL,因此返回整个表并在代码中执行查询的 Where 部分?
换言之,因为您编写条件而忽略了 LINQ 可以翻译的任何合理方法。
如果 searchRequest.Surname 为 null,则不要选择。
var query = context.GetTable<Player>(*first condition);

if (!string.IsNullOrEmpty(searchRequest.Surname) {
query = query.Where (x=> x.surname.StartsWIth (searchRequest.Surname);
}

没有人说你必须在一个运行中定义整个LINQ部分。这在编写手动SQL时是可怕的,使用LINQ时也同样可怕。一个返回结果为IQueryable的LINQ表达式和这样的链接是明确支持的。我们高效地对数亿行进行LINQ操作,看起来很棒 - 但只有因为我们没有像你那样编写糟糕的代码。

你的第二个问题也是一样的 - 你从错误的方面攻击问题,通过“强制”LINQ使用低效的搜索模式。做一个带有group by的select,然后在客户端与其他表进行连接。


2
拼写检查?我在阅读你回答的后半部分时遇到了严重的问题。 - Liam Dawson
感谢TomTom, 我有几个问题。你建议的查询对大小写敏感吗?例如,如果我搜索“smith”,它是否也会匹配“Smith”?你提到只包括非空搜索字段是有道理的,我已经从实施这种方法中极大地改进了我的第一个查询,但是你能否详细说明一下你对第二部分查询的建议? - Boob
这完全取决于你的数据库。StartsWith被转换为LIKE - 是否区分大小写取决于SQL服务器中定义的表格排序规则。 - TomTom

0

LINQPad 可以帮助您在本地调试 LINQ 语句。

当调试 LINQ to SQL 查询时,您还可以使用 SQL Server Profiler,它不仅会显示 .NET 将查询翻译成的内容,还会显示发送到数据库的其他所有内容。这在尝试解决将 LINQ 查询转换为非常长的等效 SQL 查询时的性能问题时也非常有用。

希望这可以帮到您。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接