当按用户和日期分组我们时,我正在为交易创建一个选择,并且我还需要显示累加器。 结果是正确的,但处理此查询的时间为60s。

我正在使用ef core 2.2,并且尝试使用类似的linq表达式,但响应时间相同。

public async Task<ListDataPagination<AdvanceIn, TotalizerAdvanceInDate>> AdvanceInDateAsync(int page, int? limit=15)
        {
            IQueryable<AdvanceIn> query;

            var data = new ListDataPagination<AdvanceIn, TotalizerAdvanceInDate>();

            query = Context.SaleTransaction
                .Include(s => s.AdminSale)
                .ThenInclude(a => a.PlaceCategory)
                .Include(s => s.Transaction)
                .Where(s => s.PayIn.Date <= DateTimeOffset.UtcNow.Date.AddDays(6) 
                    && s.Paid == false
                    && s.ProcessingPaid == false
                    && (s.Transaction.Status == TransactionStatus.Authorized || s.Transaction.Status == TransactionStatus.Paid) )
                .GroupBy(s => new { s.AdminSaleId, s.PayIn.Date })
                .Select(s => new AdvanceIn()
                {
                    Count = s.Count(),
                    NetAmountSum = s.Select(t => t.NetAmount).Sum(),
                    GrossAmountSum = s.Select(t => t.Transaction.GrossAmountWithoutSaleDiscount).Sum(),
                    AdminSale = new SaleTransferReadModel {
                        Id = s.Select(t => t.AdminSale).First().Id,
                        PlaceName = s.Select(t => t.AdminSale).First().PlaceName,
                        PlacePhoto = s.Select(t => t.AdminSale).First().PlacePhoto
                    },
                    PayIn = s.Select(t => t.PayIn).First(),
                    SaleTransactionId = String.Join(",", s.Select(x => x.Id.ToString()))
                })
                .OrderBy(s => s.PayIn);

            var list = await query.AsNoTracking().ToListAsync();
            data.Totalizer = new  TotalizerAdvanceInDate {
                Count = list.Sum(t => t.Count),
                NetAmountSum = list.Sum(a => a.NetAmountSum),
                GrossAmountSum = list.Sum(a => a.GrossAmountSum)
            };

            data.Page = page;
            data.TotalItems = list.Count();
            data.TotalPages = data.TotalItems / limit.Value;

            data.Data = query.Skip(limit.Value * page)
                   .Take(limit.Value)
                   .ToList();


            data.PageTotalizer = new TotalizerAdvanceInDate {
                Count = data.Data.Sum(a => a.Count),
                NetAmountSum = data.Data.Sum(a => a.NetAmountSum),
                GrossAmountSum = data.Data.Sum(a => a.GrossAmountSum)
            };

            return data;
        }

我希望减少获取此查询响应的时间。

#1楼 票数:0

一些建议:

  1. 正如NetMage指出的那样,您的第一个.ToList()调用是一个主要问题。 这将整个集合具体化到内存中,这意味着将所有这些数据从DbServer拉到Web服务器。 据我所知,这样做只是为了计数。

更新的代码:

query = Context.SaleTransaction
               .Where(s => s.PayIn.Date <= DateTimeOffset.UtcNow.Date.AddDays(6) 
                    && s.Paid == false
                    && s.ProcessingPaid == false
                    && (s.Transaction.Status == TransactionStatus.Authorized || s.Transaction.Status == TransactionStatus.Paid) )
                .GroupBy(s => new { s.AdminSaleId, s.PayIn.Date });
var rowCount = query.Count();

这将执行一个查询以获取组数,而不会撤回所有数据。

  1. 使用投影( Select )时,不需要使用Include语句。 这些仅适用于在检索实际实体图时(例如在更新期间)。

  2. 接下来,一旦您从Count计算了您的分页数字:

--

data.Data = await query.Select(s => new AdvanceIn()
    {
       Count = s.Count(),
       NetAmountSum = s.Select(t => t.NetAmount).Sum(),
       GrossAmountSum = s.Select(t => t.Transaction.GrossAmountWithoutSaleDiscount).Sum(),
       AdminSale =  s.AdminSale.OrderBy(/* ?? */).Select(a => new SaleTransferReadModel 
       {
           Id = a.Id,
           PlaceName = a.PlaceName,
           PlacePhoto = a.PlacePhoto
       }).First(),
       PayIn = s.Select(t => t.PayIn).First(), // Nope! don't return an Entity. Get a value or create a ViewModel like SaleTransferReadModel.
       SaleTransactionId = String.Join(",", s.Select(x => x.Id.ToString())) // This might not work for EF2SQL... Consider returning the list of IDs and projecting to a Display String in the ViewModel.
    }).OrderBy(s => s.PayIn)
    .Skip(limit.Value * page)
    .Take(limit.Value)
    .ToListAsync();

这将运行第二个查询,以仅从数据库中拉回所选数据页面。 我会考虑在此处使用async来允许您的Web服务器在此查询运行时处理请求,这可能需要一秒钟左右的时间,具体取决于所涉及的数据。

此处的主要更改/注意事项:不要重复“ First调用”以填充内部视图模型。 根据第一个所需的子记录,使用Select对其进行投影。 使用First等时,应始终包含OrderBy因为您不能依赖任何默认顺序。

接下来,代码将嵌入实体PayIn。 从PayIn中获取一个字段以将其返回或投影到ViewModel中。 您不希望在视图模型中嵌入任何实体,因为当序列化程序将其转换为JSON或其他格式时,它将触摸PayIn上的任何属性并可能触发延迟加载。

最后是ID列表上的string.Join() 可能行得通,但可能不行,并且EF核心有一个讨厌的习惯,会发出警告,称它会过早地实现查询以使其分两步进行,从而破坏了整个目的。 相反,我会在视图模型中Select ID的List<string> ,然后在执行string.Join()的视图模型上公开一个额外的属性。

public ICollection<Guid> SalesTransactionIds { get; set; } // Populate this in your Linq expression...

public string DisplaySalesTransactionIds 
{
   get { return string.Join(",", SalesTransactionIds); }
}

**注意:如果您对类型感到SalesTransactionIds.Select(x => x.ToString()) ,可以在Join内使用SalesTransactionIds.Select(x => x.ToString())

当序列化程序对其进行爬网时,视图/网格将在视图模型中获得一个名为DisplaySalesTransactionIds的字符串属性,该属性将为您提供以逗号分隔的列表。

尝试一下其中的一些,看看它是否可以加快速度。

  ask by Thuran Eduardo Crespi translate from so

未解决问题?本站智能推荐:

2回复

在.NetCore的EF核心中禁用和启用表触发器

我想通过EF核心从表中删除几行。 表上有一个触发器,该触发器不允许删除,但会向删除的列添加日期。 EF核心中是否有一种方法可以禁用触发器,然后调用Remove,然后在保存更改后再次启用触发器。 储存库功能 如何在代码内的EF核心中操纵触发器?
1回复

EF Core 和运行时定义的架构

免责声明 我试图寻找答案,但我找到的解决方案对我不起作用。 情况 我有一个 EF Core 2.2 项目,其架构在配置文件中定义。 例如,每个用户都应该有自己的环境,包括数据表、迁移表等。所以有一个配置文件(不一定在版本控制下),它定义了模式名称。 什么失败 创建迁移时,EFCore 工具将架
2回复

使用 EF Core 查询数据库时,是否可以有条件地包含或排除导航属性

在使用DbSet<T>查询数据库时,我试图有条件地包含或排除导航属性,如下所示: 如果导航属性为空,我想排除它,但在数据库中有值时包含它。 任何实现此目的的尝试都会引发异常: Message = "Include property lambda expression 'i =
3回复

ef 核心导航属性无法加载

我的应用程序是 Ef core 2.2 ,未启用延迟加载。 在 MapAddress 方法地址对象的 Country 对象为空,虽然我有 Include(a => a.Address).ThenInclude(a => a.Country) 急切地加载国家。 地图地址
1回复

如何使用空间数据进行EF Core 2.2迁移?

我正在尝试在Entity Framework Core 2.2中进行迁移,但遇到一些奇怪的错误,它应该可以正常工作,因为文档中没有提到任何有关映射代码的内容。 该命令: dotnet ef迁移添加InitialCreate 导致此错误: 属性“ Point.Boundar
2回复

如何从EF核心中的相关数据中仅获取少数属性?

这是 ASP .net EF Core。 我有2节课。 具有一对多关系的提名和用户。 提名将有指向用户 ID 的外键。 课程: 语境: 控制器GETALL: 当我为 Namination 执行 GETALL 时,我收到了“Nominee”(用户)的完整对象,包括密码内容。 我需要
1回复

如何使用EF Core中的联接表映射具有“自分层”关系的实体

我在使用现有数据库结构时遇到了一些麻烦,但不幸的是我无法更改。 我有以下表格(为简单起见缩写) 我将实体映射如下: 我确保急于在加载时加载导航属性,但仍然没有得到任何结果。 我以为它与我的映射有关,或者可能是因为DB结构和连接表不是按照惯例具有一对一映射的,它会使整个
1回复

不同的日期时间格式在 EF Core 和 LINQ 中返回错误的结果集。 DateTime.ParseExact 不起作用

我有一个 ASP.NET Core MVC 应用程序,其文化设置为en-GB使用dd/mm/yyyy的日期时间格式。 我正在使用: .NET 核心 2.1 英孚核心 2.2 SQL Server 2019 (v15) 日期列的类型为datetime2 但是,对于我的其中一