简体   繁体   中英

More efficient Linq to SQL

I've been playing around with Linq to SQL to help me search a simple DB. The DB consists of two tables, Player and Team, with each player record having a Team Id to link the two tables(Player.TeamId -> Team.Id).

To add a little complexity the Team table contains historical data for the past 10 seasons. This means that each team may have up to 10 different records in the team table, relating to the 10 seasons represented.

What I want my query to do is search for a Player which returns a list of players matching the search criteria and a list of team-mates for each of the returned players for that team, that season.

The search criteria includes Forname, Surname, (List of)Seasons and Team Name.

My query looks like this:

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);
}
}

This works and will return a list of players(playerList) who match the search criteria and for each of those players I can map their team mates from the second query results(teamMateList).

My problem is that Linq to SQL translates this into quite inefficient SQL. The first issue is that it selects out the entire Player table from the DB - I assume this is because Linq to SQL can't translate my Where clauses to standard SQL and so returns the entire table and does the Where part of the query in code?

The second problem is that when doing the second query Linq to SQL generates seperate queries to the DB for each member of the playerList. When reading the code this probably makes sense but I would have thought Linq would have been clever enough to translate this into a single query resulting in more efficient searching.

Any thoughts/suggestions on how to streamline my query?

I assume this is because Linq to SQL can't translate my Where clauses to standard SQL and so returns the entire table and does the Where part of the query in code?

Or, in other words - because you write the condition ignoring any sensible approach that LINQ could translate.

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

If searchRequest.Surname is null, then DO NOT SELECT.

var query = context.GetTable<Player>(*first condition);

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

No one says you have to define the whole LINQ part in one run. This was terrible when writing manual SQL, and it is terrible with LINQ. A LINQ expression where the result is an IQueryable again and chaining like this is explicitly supported. We do high efficient LINQ over hundreds of millions rows and it looks great - but only because we do not write the code in that bad a way you do.

Your second issue is the same - you attack the problem from the wrong side by forcing LINQ to use an inefficient search pattern. Make a select with a group by and then join client side with the other table.

LINQPad Can help you with debugging your LINQ Statements locally.

You can also use SQL Server Profiler when debugging LINQ to SQL Queries, it will not only show you what .NET is translating the query into but everything else being thrown at your DB. This is also very useful when trying to increase performance issues with LINQ Queries translating ridiculously long equivalent SQL Queries.

Hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM