Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.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
C# ef core中查询的长时间响应_C#_Entity Framework_.net Core_Ef Core 2.2 - Fatal编程技术网

C# ef core中查询的长时间响应

C# ef core中查询的长时间响应,c#,entity-framework,.net-core,ef-core-2.2,C#,Entity Framework,.net Core,Ef Core 2.2,我正在为事务创建一个select,当按用户和日期对我们进行分组时,我还需要显示累加器。结果是正确的,但处理此查询的时间为60秒 我使用的是ef core 2.2,我尝试使用类似的linq表达式,但响应时间是相同的 public async Task<ListDataPagination<AdvanceIn, TotalizerAdvanceInDate>> AdvanceInDateAsync(int page, int? limit=15) {

我正在为事务创建一个select,当按用户和日期对我们进行分组时,我还需要显示累加器。结果是正确的,但处理此查询的时间为60秒

我使用的是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;
        }
public异步任务高级数据同步(int page,int?limit=15)
{
可查询查询;
var data=new ListDataPagination();
query=Context.SaleTransaction
.包括(s=>s.AdminSale)
.然后包括(a=>a.PlaceCategory)
.Include(s=>s.Transaction)
.Where(s=>s.PayIn.Date new{s.AdminSaleId,s.PayIn.Date})
.Select(s=>newadvancein()
{
Count=s.Count(),
NetAmountSum=s.Select(t=>t.NetAmount).Sum(),
GrossAmountSum=s.Select(t=>t.Transaction.GrossAmountWithoutsAle折扣)。Sum(),
AdminSale=新的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=wait query.AsNoTracking().toListSync();
data.Totalizer=新的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*页)
.Take(limit.Value)
.ToList();
data.PageTotalizer=新的TotalizerAdvanceInDate{
Count=data.data.Sum(a=>a.Count),
NetAmountSum=data.data.Sum(a=>a.NetAmountSum),
GrossAmountSum=data.data.Sum(a=>a.GrossAmountSum)
};
返回数据;
}
我希望能够缩短获得此查询响应的时间。

一些建议:

  • 正如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();
    
    这将运行第二个查询,仅从数据库中提取所选的数据页。我会考虑在这里使用async,以允许您的web服务器在该查询运行时处理请求,因为这可能需要一秒钟左右的时间,具体取决于所涉及的数据

    此处的关键更改/注意事项:不要重复
    第一次调用来填充内部视图模型。根据第一个所需的子记录,使用
    选择
    对其进行投影。首先使用
    等。您应该始终包含一个
    OrderBy
    ,因为您不能依赖任何默认顺序

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

    最后是ID列表上的
    string.Join()
    。这可能行得通,但可能行不通,而且EF core有一个坏习惯,即抛出一个警告,警告它将过早地将一个查询具体化为两步投影,从而破坏了整个目的。相反,我会在视图模型中选择ID的
    列表,然后在视图模型上公开一个额外的属性,该属性执行
    string.Join()

    public ICollection SalesTransactionId{get;set;}//将其填充到Linq表达式中。。。
    公共字符串DisplaySalesTransactionId
    {
    获取{return string.Join(“,”,salesTransactionId);}
    }
    
    **注意:如果这让您对类型感到不安,您可以使用
    saletransactionids.Select(x=>x.ToString())
    Join

    public ICollection<Guid> SalesTransactionIds { get; set; } // Populate this in your Linq expression...
    
    public string DisplaySalesTransactionIds 
    {
       get { return string.Join(",", SalesTransactionIds); }
    }
    
    当序列化程序对此进行爬网时,视图/网格应该在视图的模型中获得一个名为DisplaySalesTransactionId的string属性,该属性将为您提供逗号分隔的列表


    试试其中的一些,看看它是否能加快速度。

    最后,这是一个SQL查询。在调试器中运行它,在调用
    toListSync
    时使用断点。查看
    query
    及其在调试器中生成的SQL。对SQL执行健全性检查。将其复制到SSMS并查看运行是否需要很长时间。然后做一件正常的事情来尝试优化查询(查看查询计划,可能添加索引等)。为什么要运行两次查询—一次创建
    列表
    ,一次设置
    数据。数据
    —为什么不在那里使用
    列表
    public ICollection<Guid> SalesTransactionIds { get; set; } // Populate this in your Linq expression...
    
    public string DisplaySalesTransactionIds 
    {
       get { return string.Join(",", SalesTransactionIds); }
    }