【问题标题】:Linq Query taking so long to executeLinq 查询需要很长时间才能执行
【发布时间】:2016-04-22 10:50:30
【问题描述】:

这是我的 linq 查询,这需要很长时间才能执行。任何人都可以建议我如何让它更快。我在这个查询中使用了一些函数来动态计算数据。当我删除这些函数时,这个查询运行得很快,但我必须使用这些函数以正确的方式获取数据。请有人建议我如何改进这个查询

  var l = from a in GetItemList(con)
                        join product in GetProductStock(con) on
                            a.Id
                            equals product.Id
                            into prodList
                        from prod in prodList.DefaultIfEmpty()
                        join brand in GetBrandStock(con) on
                            a.PbPairId equals brand.Id
                            into brandList
                        from bran in brandList.DefaultIfEmpty()
                        join pack in GetPackStock(con) on
                            a.PbpPairId equals pack.Id
                            into packList
                        from pac in packList.DefaultIfEmpty()
                        join np in RtbVoucherVoPurSalItem.GetTotalBuySellByItemForNormal(con) on a.Id equals np.ItemId
                            into npl
                        from npv in npl.DefaultIfEmpty()
                        join pp in RtbVoucherVoPurSalItem.GetTotalBuySellByItemForNormal(con) on a.Id equals pp.ItemId
                            into ppl
                        from ppv in ppl.DefaultIfEmpty()
                        select
                            new RsXtraProductListWithClosing
                                {
                                    Id = a.Id,
                                    PbPairId = a.PbPairId,
                                    PbpPairId = a.PbpPairId,
                                    ProductId = a.ProductId,
                                    BrandId = a.BrandId,
                                    PackId = a.PackId,
                                    DesignNoId = a.DesignNoId,
                                    Product = a.Product.Trim(),
                                    Brand = a.Brand.Trim(),
                                    Pack = a.Pack.Trim(),
                                    DesignNo = a.DesignNo.Trim(),
                                    QuantityUnitId = a.QuantityUnitId,
                                    RateUnitId = a.RateUnitId,
                                    AskDesignNo = a.AskDesignNo,
                                    AskCustomSize = a.AskCustomSize,
                                    AskDesignNoRate = a.AskDesignNoRate,
                                    UseBachNumber = a.UseBachNumber,
                                    UseExpDate = a.UseExpDate,
                                    UseManfacDate = a.UseManfacDate,
                                    AskD = a.AskD,
                                    AskH = a.AskH,
                                    AskW = a.AskW,
                                    SaD = a.SaD,
                                    SaH = a.SaH,
                                    SaW = a.SaW,
                                    SaleByPump = a.SaleByPump,
                                    ScalGroup = a.ScalGroup,
                                    CalculationUnitId = a.CalculationUnitId,
                                    UnitSize = a.UnitSize,
                                    LowStockQuantity = a.LowStockQuantity,
                                    OverStockQuantity = a.OverStockQuantity,
                                    SizeAs = a.SizeAs,
                                    UseDirectDiscount = a.UseDirectDiscount,
                                    Discount = a.Discount,
                                    PurchaseRate1 = a.PurchaseRate1,
                                    PurchaseRate2 = a.PurchaseRate2,
                                    PurchaseRate3 = a.PurchaseRate3,
                                    PurchaseOtherRate = a.PurchaseOtherRate,
                                    SaleRate1 = a.SaleRate1,
                                    SaleRate2 = a.SaleRate2,
                                    SaleRate3 = a.SaleRate3,
                                    SaleOtherRate = a.SaleOtherRate,
                                    LockOtherPurchaseRate = a.LockOtherPurchaseRate,
                                    LockOtherSaleRate = a.LockOtherSaleRate,
                                    LockSaleRate = a.LockSaleRate,
                                    LockPurchaseRate = a.LockPurchaseRate,
                                    ProductClosingStock = ((a.Pobu ?? prod.OpeningStock ?? 0) + (npv.Quantaty ?? 0)),
                                    ProductCClosingStock = ((a.CPobu ?? prod.COpeningStock ?? 0) + (ppv.Quantaty ?? 0)),
                                    BrandClosingStock = ((a.Bobu ?? bran.OpeningStock ?? 0) + (npv.Quantaty ?? 0)),
                                    BrandCClosingStock = ((a.CBobu ?? bran.COpeningStock ?? 0) + (ppv.Quantaty ?? 0)),
                                    PackClosingStock = ((a.Paobu ?? pac.OpeningStock ?? 0) + (npv.Quantaty ?? 0)),
                                    PackCClosingStock = ((a.CPaobu ?? pac.COpeningStock ?? 0) + (ppv.Quantaty ?? 0)),
                                    DesignNoClosingStock = ((a.Dobu ?? 0) + (npv.Quantaty ?? 0)),
                                    DesignNoCClosingStock = ((a.CDobu ?? 0) + (ppv.Quantaty ?? 0))
                                };
                return l;


and this are the other functions helping this query 

  public static IQueryable<RsXtraOpeningStock> GetPackStock(RdbCompany con)
        {
            return con.RtbInventoryProductBrandPackDesignNoPairs
                .GroupBy(p => p.BrandPackPairId).Select(
                g => new RsXtraOpeningStock
                         {
                             Id = g.Key,
                             OpeningStock = (g.Sum(m => m.OpeningStock) ?? 0),
                             COpeningStock = (g.Sum(m => m.COpenigStock) ?? 0),
                         });
        }


        public static IQueryable<RsXtraOpeningStock> GetBrandStock(RdbCompany con)
        {
            return from d in con.RtbInventoryProductBrandPackPairs
                   join pk in GetPackStock(con) on d.Id equals pk.Id
                       into pkl
                   from pkd in pkl.DefaultIfEmpty()
                   group new{d,pkd} by d.BrandPairId
                       into g
                       select new RsXtraOpeningStock
                       {
                           Id = g.Key,
                           OpeningStock = ((g.Sum(a => (decimal?)(a.d.OpeningStock ?? a.pkd.OpeningStock))??0)),
                           COpeningStock = ((g.Sum(a => (decimal?)(a.d.COpenigStock ?? a.pkd.COpeningStock))??0))
                       };
        }


        public static IQueryable<RsXtraOpeningStock> GetProductStock(RdbCompany con)
        {
            return from d in con.RtbInventoryProductBrandPairs
                   join br in GetBrandStock(con) on d.Id equals br.Id
                       into brl
                   from brd in brl.DefaultIfEmpty()
                   group new { d, brd } by d.ProductId
                       into g
                       select new RsXtraOpeningStock
                       {
                           Id = g.Key,
                           OpeningStock = ((g.Sum(a => (decimal?)(a.d.OpeningStock ?? a.brd.OpeningStock)) ?? 0)),
                           COpeningStock = ((g.Sum(a => (decimal?)(a.d.COpenigStock ?? a.brd.COpeningStock)) ?? 0))
                       };

        }






 public static IQueryable<RsXtraItemFinalBuySellByMode> GetTotalBuySellByItemForPure(RdbCompany con)
        {
            var stockActiveArray = RsXtraVoucherHelperArray.GetActiveStockVoucherType();
            return GetList(con).Where(
                a => stockActiveArray.Contains(a.FkVoucherVoMain.FkVoucher.FkVoucherGroup.VoucherType)
                     && a.FkVoucherVoMain.CompanyId == RsXtraMainInnerObj.CurrentCompany.Id
                     && a.FkVoucherVoMain.BranchId == RsXtraMainInnerObj.CurrentHierarchy.Id
                     && a.FkVoucherVoMain.Mode == RenumMode.P
                )
                .GroupBy(a => new {a.ItemId})
                .Select(a => new RsXtraItemFinalBuySellByMode
                                 {
                                     ItemId = a.Key.ItemId,
                                     Quantaty = a.Sum(c => (decimal?)c.Quantaty)
                                 });
        }


         public static IQueryable<RsXtraItemFinalBuySellByMode> GetTotalBuySellByItemForNormal(RdbCompany con)
        {
            var stockActiveArray = RsXtraVoucherHelperArray.GetActiveStockVoucherType();
            return GetList(con).Where(
                a => stockActiveArray.Contains(a.FkVoucherVoMain.FkVoucher.FkVoucherGroup.VoucherType)
                     && a.FkVoucherVoMain.CompanyId == RsXtraMainInnerObj.CurrentCompany.Id
                     && a.FkVoucherVoMain.BranchId == RsXtraMainInnerObj.CurrentHierarchy.Id
                     && a.FkVoucherVoMain.Mode != RenumMode.P
                )
                .GroupBy(a => new { a.ItemId })
                .Select(a => new RsXtraItemFinalBuySellByMode
                {
                    ItemId = a.Key.ItemId,
                    Quantaty = a.Sum(c => (decimal?)c.Quantaty)
                });
        }

【问题讨论】:

  • 我怀疑所有这些GroupBy 语句要么创建包含许多CROSS JOIN 子句的怪异SQL 语句,要么发出大量SQL 语句。您必须检查 Sql Server Profiler。您可能应该在几个 LINQ 语句中分解此任务。

标签: c# .net linq linq-to-sql


【解决方案1】:

如果使用 Linq to SQL,您可以通过 SQL Server Profile 看到究竟生成了哪些 SQL 语句。您可以在此基础上对其进行优化。但是加入这么多的对象,性能会明显下降。

【讨论】:

  • 是的,但使用此查询。 VS不显示sql语句
  • @sourabhdevpura 不是 VS,运行 SQL Server Profiler(独立程序)以查看服务器上的实际情况。生成什么查询以及它们需要多长时间。 VS 不会向您显示。
【解决方案2】:

我怀疑你会发现你的辅助函数每次被主查询调用时都会被重新评估,你应该能够通过对主查询执行 ToString() 来确认这一点并检查方法编译器生成的语法。如果我是你,我会预先为每个可能的输入缓存助手的结果,并将结果存储在字典中,然后你的主查询可以在 O(1) 时间内查找。

【讨论】:

    猜你喜欢
    • 2018-07-06
    • 1970-01-01
    • 2021-12-25
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    • 2011-01-17
    • 2012-12-03
    相关资源
    最近更新 更多