【问题标题】:Is it a lazy loading query or Eager Loading ? , Slow Query, Performance needed please是延迟加载查询还是急切加载? , 查询慢, 需要性能请
【发布时间】:2011-08-23 10:18:05
【问题描述】:

首先,我想知道这个查询是延迟加载还是急切加载。我在这两个方面都阅读了很多,但不确定我是否了解彼此之间的区别。

2- 我得到这个查询,这个查询需要很长时间才能执行。当您看到此查询时,任何人都有一些建议。我会做所有需要的修改来加快这个查询。

注意:我只是想听听您对这个查询和方法的意见。

非常感谢。

public SearchLocationViewModel GetSearchLocationViewModel(  string CivicNumber = null ,
                                                                    string Street = null,
                                                                    string City = null,
                                                                    List<int?> ListCountryID = null,
                                                                    List<int?> ListStateID = null,
                                                                    int IsActive =1,
                                                                    string SortField ="FileNumber",
                                                                    string SortDirection = "asc" ,
                                                                    List<int?> GrpDescID1 = null,
                                                                    List<int?> GrpDescID2 = null,
                                                                    List<int?> GrpDescID3 = null,
                                                                    List<int?> GrpDescID4 = null,
                                                                    int LocationTypeID = -1,
                                                                    List<int?> ListUsageID = null)
        {

            if (GrpDescID1 == null)
            {
                GrpDescID1 = new List<int?>();
            }

            if (GrpDescID2 == null)
            {
                GrpDescID2 = new List<int?>();
            }

            if (GrpDescID3 == null)
            {
                GrpDescID3 = new List<int?>();
            }

            if (GrpDescID4 == null)
            {
                GrpDescID4 = new List<int?>();
            }

            if (ListCountryID == null)
            {
                ListCountryID = new List<int?>();
            }

            if (ListStateID == null)
            {
                ListStateID = new List<int?>();
            }

            if (ListUsageID == null)
            {
                ListUsageID = new List<int?>();
            }
            GrpDescID1.Remove(GrpDescID1.SingleOrDefault(p => p < 0));
            GrpDescID2.Remove(GrpDescID2.SingleOrDefault(p => p < 0));
            GrpDescID3.Remove(GrpDescID3.SingleOrDefault(p => p < 0));
            GrpDescID4.Remove(GrpDescID4.SingleOrDefault(p => p < 0));
            ListCountryID.Remove(ListCountryID.SingleOrDefault(p => p < 0));
            ListStateID.Remove(ListStateID.SingleOrDefault(p => p < 0));
            ListUsageID.Remove(ListUsageID.SingleOrDefault(p => p < 0));

            int lang = BaseStaticClass.CurrentLangID();
            int UserID = Convert.ToInt32(Session["UserID"]);
            SearchLocationViewModel ViewModel = InitSearchViewModel();
            IGrpRepository repGrp = new GrpRepository(_db);
            ICountryRepository repCountry = new CountryRepository(_db);
            IProvinceRepository repProvince = new ProvinceRepository(_db);

            ViewModel.Perm = repPermission;
            ViewModel. CivicNumber = CivicNumber ;
            ViewModel. Street = Street;
            ViewModel. City = City;
            ViewModel. IsActive =IsActive;
            ViewModel. SortField =SortField;
            ViewModel. SortDirection = SortDirection ;

            ViewModel.ListCountry = repCountry.GetCountryForSearchByUser(true,UserID);
            ViewModel.ListProvince = repProvince.GetProvinceSearchByUserID(true, UserID);

            ViewModel.ListGrpDescID1 =GrpDescID1;
            ViewModel.ListGrpDescID2 = GrpDescID2;
            ViewModel.ListGrpDescID3 = GrpDescID3;
            ViewModel.ListGrpDescID4 = GrpDescID4;
            ViewModel.ListCountryID = ListCountryID;
            ViewModel.ListStateID = ListStateID;
            ViewModel.LocationTypeID = LocationTypeID;
            ViewModel.ListUsageID = ListUsageID;

            var LocationType = new SelectList(repGeneric.GetTextByCurrentLang<LocationType, LocationTypeText>(), "ID", "Txt").ToList();
            bc.AddDropdownSearchValueNoNew(ref LocationType);

            var ListUsage = new SelectList(repGeneric.GetTextByCurrentLang<Usage, UsageText>(), "ID", "Txt").ToList();

            ViewModel.ListUsage = ListUsage;
            ViewModel.ListLocationType = LocationType;
            var ListGrp1 = new SelectList(repGrp.GetAllGrpDescTextForUserByLevel(UserID, 1).AsEnumerable(), "GrpDescID", "GrpDescTxt").ToList();
            var ListGrp2 = new SelectList(repGrp.GetAllGrpDescTextForUserByLevel(UserID, 2).AsEnumerable(), "GrpDescID", "GrpDescTxt").ToList();
            var ListGrp3 = new SelectList(repGrp.GetAllGrpDescTextForUserByLevel(UserID, 3).AsEnumerable(), "GrpDescID", "GrpDescTxt").ToList();
            var ListGrp4 = new SelectList(repGrp.GetAllGrpDescTextForUserByLevel(UserID, 4).AsEnumerable(), "GrpDescID", "GrpDescTxt").ToList();


            var t1 = ListGrp1.Select(s => (int?)Convert.ToInt32(s.Value));
            var t2 = ListGrp2.Select(s => (int?)Convert.ToInt32(s.Value));
            var t3 = ListGrp3.Select(s => (int?)Convert.ToInt32(s.Value));
            var t4 = ListGrp4.Select(s => (int?)Convert.ToInt32(s.Value));

            ViewModel.ListGrp1 = ListGrp1;
            ViewModel.ListGrp2 = ListGrp2;
            ViewModel.ListGrp3 = ListGrp3;
            ViewModel.ListGrp4 = ListGrp4;

            ViewModel.ListGrpTogether = new List<SelectListItem>();

            if(ViewModel.GrpName1 != "")
                ViewModel.ListGrpTogether.Add(new SelectListItem() { Text = ViewModel.GrpName1 ,Value = "1"});

            if (ViewModel.GrpName2 != "")
                ViewModel.ListGrpTogether.Add(new SelectListItem() { Text = ViewModel.GrpName2, Value = "2" });

            if (ViewModel.GrpName3 != "")
                ViewModel.ListGrpTogether.Add(new SelectListItem() { Text = ViewModel.GrpName3, Value = "3" });

            if (ViewModel.GrpName4 != "")
                ViewModel.ListGrpTogether.Add(new SelectListItem() { Text = ViewModel.GrpName4, Value = "4" });

            ViewModel.ListGrpTogether.Insert(0, new SelectListItem() { Text = ViewRes.GeneralString.Choose, Value = "-1", Selected = true });

            int iUserID = Convert.ToInt32(Session["UserID"]);
            //this is use for Permission
            //Get all the user permission about group and province
            IEnumerable<int?> usrGrpDesc = _db.UserGroupDescs.Where(p => p.UserID == iUserID).Select(s => s.GrpDescID);
            IEnumerable<int?> usrProvince = _db.UserProvinces.Where(p => p.UserID == iUserID).Select(s => s.PrvID);

            var ListLocation = from s in _db.Locations.Where(p => 
                                                          p.IsDelete == false &&
                                                         (IsActive < 0 || IsActive == (p.IsActive == true ? 1 : 0)) &&
                                                         (LocationTypeID < 0 || LocationTypeID == p.LocationTypeID) &&
                                                         (City == null || p.Address.City.CityName.Contains(City)) &&
                                                         (ListUsageID.Count() == 0 || p.Premises.Select(gs => gs.UsageID).Intersect(ListUsageID).Any()) &&
                                                         (ListCountryID.Count() == 0 || ListCountryID.Any(pl => pl == p.Address.City.Province.Country.CtryID)) &&
                                                         (ListStateID.Count() == 0 || ListStateID.Any(pl => pl == p.Address.City.Province.PrvID)) &&
                                                         (Street == null || p.Address.Street.Contains(Street)) &&
                                                         (CivicNumber == null || p.Address.CivicNumber.Contains(CivicNumber)) &&
                                                         ((GrpDescID1.Count() == 0 )|| p.GroupLocations.Select(gs => gs.GrpDescID).Intersect(GrpDescID1).Any()) &&
                                                         ((GrpDescID2.Count() == 0)|| p.GroupLocations.Select(gs => gs.GrpDescID).Intersect(GrpDescID2).Any()) &&
                                                         ((GrpDescID3.Count() == 0) || p.GroupLocations.Select(gs => gs.GrpDescID).Intersect(GrpDescID3).Any()) &&
                                                         ((GrpDescID4.Count() == 0 )  || p.GroupLocations.Select(gs => gs.GrpDescID).Intersect(GrpDescID4).Any()) &&
                                                         (p.GroupLocations.Select(gs => gs.GrpDescID).Intersect(usrGrpDesc).Any()) &&
                                                         ((p.Address.City == null || usrProvince.Any(ps => ps.Value == p.Address.City.PrvID)))
                                                         )

                               select new LocationViewModel()
                               {
                                   LocationID = s.LocationID,
                                   LocationTypeID = s.LocationTypeID,
                                   Long = s.Address.Longitude,
                                   Lat = s.Address.Latitude,
                                   FileNumber = s.LocationFile,
                                   State = s.Address.City.Province.PrvName,
                                   City = s.Address.City.CityName,
                                   Address = s.Address.CivicNumber + " " + s.Address.Street,
                                   Status = s.LocationType.LocationTypeTexts.Where(h => h.Txt != "" && h.LangID == lang || h.LangID == 1).OrderByDescending(g => g.LangID).FirstOrDefault().Txt,
                                   ListGroupe1 = s.GroupLocations.Where(g=>g.GrpDesc.Grp.GrpLevel == 1).Select(grpLoc => grpLoc.GrpDesc.GrpDescTexts.Where(h => h.GrpDescTxt != "" && (h.LangID == lang || h.LangID == 1)).OrderByDescending(g => g.LangID).FirstOrDefault()).Select(txt => txt.GrpDescTxt),
                                   ListGroupe2 = s.GroupLocations.Where(g => g.GrpDesc.Grp.GrpLevel == 2).Select(grpLoc => grpLoc.GrpDesc.GrpDescTexts.Where(h => h.GrpDescTxt != "" && (h.LangID == lang || h.LangID == 1)).OrderByDescending(g => g.LangID).FirstOrDefault()).Select(txt => txt.GrpDescTxt),
                                   ListGroupe3 = s.GroupLocations.Where(g=>g.GrpDesc.Grp.GrpLevel == 3).Select(grpLoc => grpLoc.GrpDesc.GrpDescTexts.Where(h => h.GrpDescTxt != "" && (h.LangID == lang || h.LangID == 1)).OrderByDescending(g => g.LangID).FirstOrDefault()).Select(txt => txt.GrpDescTxt),
                                   ListGroupe4 = s.GroupLocations.Where(g=>g.GrpDesc.Grp.GrpLevel == 4).Select(grpLoc => grpLoc.GrpDesc.GrpDescTexts.Where(h => h.GrpDescTxt != "" && (h.LangID == lang || h.LangID == 1)).OrderByDescending(g => g.LangID).FirstOrDefault()).Select(txt => txt.GrpDescTxt),
                                   DefaultImgPath = s.LocationPictures.Where(p=>p.IsDefault == true && p.IsActive == true).FirstOrDefault().FilePath,
                                   HasPremises = s.Premises.Any(p => p.IsActive == true && p.IsDelete == false)

                               };
ViewModel.ListLocation = ListLocation.ToList();
return ViewModel;
}

【问题讨论】:

    标签: asp.net-mvc-2 entity-framework-4 lazy-loading eager-loading


    【解决方案1】:

    延迟加载是将对象的初始化推迟到需要它的时候。如果您将ListLocation 返回给它的调用者,正如您在上面所写的那样,没有.ToList()(或其他),那么您将懒惰地使用它。

    预加载是在定义查询时收集查询结果。在这种情况下,它将一次检索所有 LINQ 查询的结果(在构造查询时)。通常.ToList().Single() 或其他会为您执行此操作。

    我怀疑您稍后会在代码中使用 LINQ 查询 (var ListLocation) 的结果。您上面的代码使用了延迟加载的方法。

    你表明你正在调用.ToList(),所以你确实在使用急切加载;即使它在不同的语句/代码行上。

    性能:我不是 100% 认为这是您的性能问题,但我会使用扩展方法 .WhereIf() 将您的 LINQ 重构为类似的东西。它的阅读和写作要容易得多。

     var ListLocation =  from s in _db.Locations
            .Where(p =>  p.IsDelete == false)
            .WhereIf(IsActive >= 0, p=> IsActive == (p.IsActive == true ? 1 : 0))
            .WhereIf(LocationTypeID >= 0, p=> LocationTypeID == p.LocationTypeID
            .WhereIf(City!=null, p=> p.Address.City.CityName.Contains(City))                //etc
    

    【讨论】:

    • 好的,我忘记了 2 行代码。我添加了它( Viewmodel.ListLocation = ListLocation.ToList() )。如果我理解,虽然我不使用 .ToList() 或其他,但我正在延迟加载。你有什么想法可以改进这个查询吗?
    • 如果你只用布尔逻辑编写 WhereIf 会更有意义".Where(p =&gt; City!=null &amp;&amp; p.Address.City.CityName.Contains(City)).
    • @Ryan:这是否建议增加或减少生成的 SQL 的复杂性(由 OP 评估)或查询的可读性?我猜WhereIf 的意义在于,根据提供的 bool 的结果,lambda 被链接到查询上。感谢您的想法!
    • @campbell 我不确定。我一般不看生成的sql。
    【解决方案2】:

    如果您正在使用它并且它有效,那么您可能是延迟加载,因为您没有对 .Include() 的任何调用。

    【讨论】:

    • 每次您依赖数据库中的数据时,您都在强制进行往返。尝试使用分析器查看瓶颈在哪里:efprof.com
    猜你喜欢
    • 2013-07-05
    • 1970-01-01
    • 1970-01-01
    • 2015-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 2023-03-25
    相关资源
    最近更新 更多