0

EF5 と汎用リポジトリ、SQL Server 2008 db への作業単位パターンを使用した次の LINQ クエリがあります。

        var countriesArr = GetIdsFromDelimStr(countries);
        var competitionsArr = GetIdsFromDelimStr(competitions);
        var filterTeamName = string.Empty;

        if (teamName != null)
        {
            filterTeamName = teamName.ToUpper();
        }

        using (var unitOfWork = new FootballUnitOfWork(ConnFooty))
        {

            // give us our selection of teams
            var teams =
                (from team in
                     unitOfWork.TeamRepository.Find()
                 where ((string.IsNullOrEmpty(filterTeamName) || team.Name.ToUpper().Contains(filterTeamName)) &&
                        (countriesArr.Contains(team.Venue.Country.Id) || countriesArr.Count() == 0))
                 select new
                            {
                                tId = team.Id
                            }).Distinct();

            // give us our selection of contests
            var conts = (
                            from cont in
                                unitOfWork.ContestRepository.Find(
                                    c =>
                                    ((c.ContestType == ContestType.League && competitionsArr.Count() == 0) ||
                                     (competitionsArr.Contains(c.Competition.Id) && competitionsArr.Count() == 0)))
                            select new
                                       {
                                           contId = cont.Id
                                       }
                        ).Distinct();

            // get selection of home teams based on contest
            var homecomps = (from fixt in unitOfWork.FixtureDetailsRepository.Find()
                             where
                                 teams.Any(t => t.tId == fixt.HomeTeam.Id) &&
                                 conts.Any(c => c.contId == fixt.Contest.Id)
                             select new
                                        {
                                            teamId = fixt.HomeTeam.Id,
                                            teamName = fixt.HomeTeam.Name,
                                            countryId = fixt.HomeTeam.Venue.Country.Id != null ? fixt.HomeTeam.Venue.Country.Id : 0,
                                            countryName = fixt.HomeTeam.Venue.Country.Id != null ? fixt.HomeTeam.Venue.Country.Name : string.Empty,
                                            compId = fixt.Contest.Competition.Id,
                                            compDesc = fixt.Contest.Competition.Description
                                        }).Distinct();

            // get selection of away teams based on contest
            var awaycomps = (from fixt in unitOfWork.FixtureDetailsRepository.Find()
                             where
                                 teams.Any(t => t.tId == fixt.AwayTeam.Id) &&
                                 conts.Any(c => c.contId == fixt.Contest.Id)
                             select new
                             {
                                 teamId = fixt.AwayTeam.Id,
                                 teamName = fixt.AwayTeam.Name,
                                 countryId = fixt.AwayTeam.Venue.Country.Id != null ? fixt.AwayTeam.Venue.Country.Id : 0,
                                 countryName = fixt.AwayTeam.Venue.Country.Id != null ? fixt.AwayTeam.Venue.Country.Name : string.Empty,
                                 compId = fixt.Contest.Competition.Id,
                                 compDesc = fixt.Contest.Competition.Description
                             }).Distinct();

            // ensure that we return the max competition based on id for home teams
            var homemax = (from t in homecomps
                           group t by t.teamId
                               into grp
                               let maxcomp = grp.Max(g => g.compId)
                               from g in grp
                               where g.compId == maxcomp
                               select g).Distinct();

            // ensure that we return the max competition based on id for away teams
            var awaymax = (from t in awaycomps
                           group t by t.teamId
                               into grp
                               let maxcomp = grp.Max(g => g.compId)
                               from g in grp
                               where g.compId == maxcomp
                               select g).Distinct();

            var filteredteams = homemax.Union(awaymax).OrderBy(t => t.teamName).AsQueryable();

ご覧のとおり、WebAPI に渡される次の形式を返したいので、UI で関連付けることができる型に結果をキャストします。

基本的に私たちがやろうとしていることは、ホームとアウェイのチームをフィクスチャから外すことです。これらのフィクスチャには、競技に関連するコンテストがあります。次に、グループ化から最高の競技 ID を取得し、これがそのチームと共に返されます。国は、会場 ID に基づいてチームに関連付けられています。私が最初にこれを行っていたとき、LINQ で OR 結合を行う方法を理解するのに問題がありました。そのため、ホーム チームとアウェイ チームを取得し、それらをベースにグループ化することに分割しました。競争で、それらを一緒に結合します。

現在のテーブル サイズの目安は、fixtures が 7840 行、teams が 8581 行、contests が 337 行、competitions が 96 行です。サッカーに関連しているため、急速に増加する可能性が高いテーブルはフィクスチャ テーブルです。

最終的に得たい出力は

チームID、チーム名、国ID、国名、大会ID、大会名

フィルタリングを使用しないと、このクエリは平均で約 5 秒かかります。これを高速化する方法についてアイデアやヒントがあるかどうか疑問に思っているだけです。

前もって感謝します マーク

4

1 に答える 1