Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
加快LINQ查询-EF5_Linq_Entity Framework_Optimization_Entity Framework 5 - Fatal编程技术网

加快LINQ查询-EF5

加快LINQ查询-EF5,linq,entity-framework,optimization,entity-framework-5,Linq,Entity Framework,Optimization,Entity Framework 5,我有以下使用EF5和通用存储库的LINQ查询,SQL Server 2008 db的工作单元模式 var countriesArr = GetIdsFromDelimStr(countries); var competitionsArr = GetIdsFromDelimStr(competitions); var filterTeamName = string.Empty; if (teamName != null)

我有以下使用EF5和通用存储库的LINQ查询,SQL Server 2008 db的工作单元模式

        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时遇到了问题,这就是为什么我将其分为主队和客队,然后根据竞争对他们进行分组,然后将他们联合在一起

当前表格大小的概念是固定装置有7840行,团队有8581行,竞赛有337行,竞赛有96行。可能快速增长的表格是赛程表,因为这与足球有关

我们想要得到的结果是

球队Id、球队名称、国家Id、国家名称、比赛Id、比赛名称

使用无过滤,此查询平均需要5秒左右,只是想知道是否有人对如何加快查询速度有任何想法/建议


提前感谢Mark

我无法判断它是否会加快速度,但您的
homemax
awaymax
查询可能会被忽略

var homemax = from t in homecomps
              group t by t.teamId into grp
              select grp.OrderByDescending(x => x.compId).FirstOrDefault();

var awaymax = from t in awaycomps
              group t by t.teamId into grp
              select grp.OrderByDescending(x => x.compId).FirstOrDefault();
此外,当您编写一个非常大的查询时,如果将其分解为几个较小的查询以获取中间结果,它的性能可能会更好。有时,对数据库的多次往返比数据库引擎无法找到良好执行计划的一个非常大的查询执行得更好

另一件事是所有这些
Distinct()
s。你总是需要它们吗?我认为您可以不这样做,因为您总是从一个表中获取数据,而不加入子集合。移除它们可能会节省一大笔钱


另一个优化可能是删除
ToUpper
。比较是由SQL中的数据库引擎完成的,数据库可能具有不区分大小写的排序规则。如果是这样的话,即使您希望它是区分大小写的,比较也永远不会区分大小写!像
Name.ToUpper
这样的结构取消了对
Name
的任何索引的使用(它不是)。

在我看来,EF不是这类查询的合适工具。可能结果sql语句很糟糕。我建议使用存储过程和/或视图。当然,您可以从EF调用它。分析查询计划以确定是否缺少任何索引您的工作单元模式支持延迟加载吗?如果不这样做,将大大提高速度。@davidecardi无论您选择用什么编写查询,如果您做得不好,它将无法在SQL中正常工作。EF和SPs也是如此。您应该始终检查生成的SQL/查询计划,如果它不好,请修复您的查询…嗨,Gert,谢谢您的回复。关闭延迟加载使其下降到4秒左右,关闭distincts使其下降到3.75秒左右。当我尝试应用您的分组示例时,.First()部分出现错误(查询体必须以select子句或group子句结尾),最后一个linq部分类型参数中的union子句出现错误,无法从用法中推断。所以我不确定这是否被错误地复制了。我做了一些修改,并添加了另一个我想到的东西。太棒了,修改了,时间刚刚超过3秒,谢谢你的帮助。