更高效的Linq to SQL

时间:2012-02-07 10:43:36

标签: c# sql linq linq-to-sql

我一直在玩Linq to SQL来帮助我搜索一个简单的数据库。 数据库由两个表组成,即Player和Team,每个玩家记录都有一个Team Id来链接两个表(Player.TeamId - > Team.Id)。

为了增加一点复杂性,Team表包含过去10个赛季的历史数据。这意味着每个团队最多可以有10个不同的记录 团队表,与10个季节有关。

我想要查询的是搜索一个播放器,该播放器返回符合搜索条件的玩家列表,以及该团队每个返回玩家的队友列表。

搜索条件包括Forname,Surname,(列表)季节和团队名称。

我的查询如下:

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成员生成单独的DB查询。在阅读代码时,这可能有意义,但我认为Linq会非常聪明地将其转换为单个查询,从而提高搜索效率。

有关如何简化查询的任何想法/建议?

2 个答案:

答案 0 :(得分:1)

  

我认为这是因为Linq to SQL无法将我的Where子句转换为标准SQL等等   返回整个表并在代码中执行查询的Where部分?

或者换句话说 - 因为你写的条件忽略了LINQ可以翻译的任何明智的方法。

  

string.Equals(p.Surname,(searchRequest.Surname ?? p.Surname

如果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很糟糕。显式支持LINQ表达式,其中结果再次为IQueryable并且链接为此类链接。我们在数亿行上运行高效的LINQ,看起来很棒 - 但这只是因为我们不会以那么糟糕的方式编写代码。

您的第二个问题是相同的 - 您通过强制 LINQ使用效率低下的搜索模式从错误的方面解决问题。使用group by进行选择,然后将客户端与另一个表连接。

答案 1 :(得分:0)

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

在调试LINQ to SQL查询时,您也可以使用SQL Server Profiler,它不仅会向您显示.NET正在将查询转换为什么,而且还会向您的数据库抛出所有其他内容。当尝试使用LINQ查询来翻译可笑的长等效SQL查询时,这也非常有用。

希望这会有所帮助。