Linq2Sql: query - subquery optimisation

元气小坏坏 提交于 2019-12-31 06:17:04

问题


I have the following query:

            IList<InfrStadium> stadiums =
                (from sector in DbContext.sectors
                 where sector.Type=typeValue
                 select new InfrStadium(sector.TeamId)
                ).ToList();

and InfrStadium class constructor:

    private InfrStadium(int teamId)
    {
        IList<Sector> teamSectors = (from sector in DbContext.sectors
                                     where sector.TeamId==teamId
                                     select sector)
                                     .ToList<>();
        ... work with data
    }

Current implementation perform 1+n queries, where n - number of records fetched the 1st time.

I want to optimize that.

And another one I would love to do using 'group' operator in way like this:

            IList<InfrStadium> stadiums =
                (from sector in DbContext.sectors
                 group sector by sector.TeamId into team_sectors
                 select new InfrStadium(team_sectors.Key, team_sectors)
                ).ToList();

with appropriate constructor:

    private InfrStadium(int iTeamId, IEnumerable<InfrStadiumSector> eSectors)
    {
        IList<Sector> teamSectors = eSectors.ToList();

        ... work with data
    }

But attempt to launch query causes the following error:

Expression of type 'System.Int32' cannot be used for constructor parameter of type 'System.Collections.Generic.IEnumerable`1[InfrStadiumSector]'

Question 1:

Could you please explain, what is wrong here, I don't understand why 'team_sectors' is applied as 'System.Int32'?

I've tried to change query a little (replace IEnumerable with IQueryeable):

            IList<InfrStadium> stadiums =
                (from sector in DbContext.sectors
                 group sector by sector.TeamId into team_sectors
                 select new InfrStadium(team_sectors.Key, team_sectors.AsQueryable())
                ).ToList();

with appropriate constructor:

    private InfrStadium(int iTeamId, IQueryeable<InfrStadiumSector> eSectors)
    {
        IList<Sector> teamSectors = eSectors.ToList();

        ... work with data
    }

In this case I've received another but similar error:

Expression of type 'System.Int32' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable1[InfrStadiumSector]' of method 'System.Linq.IQueryable1[InfrStadiumSector] AsQueryableInfrStadiumSector'

Question 2:

Actually, the same question: can't understand at all what is going on here...

P.S. I have another to optimize query idea (describe here: Linq2Sql: query optimisation) but I would love to find a solution with 1 request to DB).


回答1:


First, pull the data locally and put it into a structure that meets your needs.

ILookup<int, InfrStadiumSector> sectorLookup =
(
  from sector in DbContext.sectors
  where sector.Type == typeValue
  select sector
).ToLookup(sector => sector.TeamId);

Then project each grouping in that lookup into an instance of InfrStadium (without going back to the database)...

IList<InfrStadium> stadiums = sectorLookup
  .Select(x => new InfrStadium(x.Key, x))
  .ToList();

And that projection uses this constructor.

private InfrStadium(int iTeamId, IEnumerable<InfrStadiumSector> eSectors)



回答2:


I can't be sure what's going on without a little experimentation. Are you sure of the order of your parameters in the constructor? If so, then it might be a problem translating the expression. You might want to try materializing the query before you attempt to construct the InfrStadium objects. I'll rewrite using extension methods as I think it will be easier to read.

var stadiums = DbContext.sectors
                        .ToLookup( s => s.TeamId )
                        .Select( g => new InfrStadium( g.Key, g ) )
                        .ToList();


来源:https://stackoverflow.com/questions/4697982/linq2sql-query-subquery-optimisation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!