我在Job_Details
表中至少有10万个数据,并且我正在使用Entity Framework映射数据。
这是代码:
public GetJobsResponse GetImportJobs()
{
GetJobsResponse getJobResponse = new GetJobsResponse();
List<JobBO> lstJobs = new List<JobBO>();
using (NSEXIM_V2Entities dbContext = new NSEXIM_V2Entities())
{
var lstJob = dbContext.Job_Details.ToList();
foreach (var dbJob in lstJob.Where(ie => ie.IMP_EXP == "I" && ie.Job_No != null))
{
JobBO job = MapBEJobforSearchObj(dbJob);
lstJobs.Add(job);
}
}
getJobResponse.Jobs = lstJobs;
return getJobResponse;
}
我发现这一行执行大约需要2-3分钟
var lstJob = dbContext.Job_Details.ToList();
我该如何解决这个问题?
答案 0 :(得分:1)
使用示例概述性能问题:(请参见内联注释)
public GetJobsResponse GetImportJobs()
{
GetJobsResponse getJobResponse = new GetJobsResponse();
List<JobBO> lstJobs = new List<JobBO>();
using (NSEXIM_V2Entities dbContext = new NSEXIM_V2Entities())
{
// Loads *ALL* entities into memory. This effectively takes all fields for all rows across from the database to your app server. (Even though you don't want it all)
var lstJob = dbContext.Job_Details.ToList();
// Filters from the data in memory.
foreach (var dbJob in lstJob.Where(ie => ie.IMP_EXP == "I" && ie.Job_No != null))
{
// Maps the entity to a DTO and adds it to the return collection.
JobBO job = MapBEJobforSearchObj(dbJob);
lstJobs.Add(job);
}
}
// Returns the DTOs.
getJobResponse.Jobs = lstJobs;
return getJobResponse;
}
首先:将WHERE子句传递给EF,以传递给数据库服务器,而不是将所有实体加载到内存中。
public GetJobsResponse GetImportJobs()
{
GetJobsResponse getJobResponse = new GetJobsResponse();
using (NSEXIM_V2Entities dbContext = new NSEXIM_V2Entities())
{
// Will pass the where expression to be DB server to be executed. Note: No .ToList() yet to leave this as IQueryable.
var jobs = dbContext.Job_Details..Where(ie => ie.IMP_EXP == "I" && ie.Job_No != null));
接下来,使用SELECT加载DTO。通常,这些数据所包含的数据不会像主要实体那样多,并且只要您使用IQueryable,就可以根据需要加载相关数据。同样,它将被发送到数据库服务器,因此您不能在此处使用“ MapBEJobForSearchObj”之类的功能,因为数据库服务器不知道该功能。您可以选择一个简单的DTO对象,也可以选择一个匿名类型来传递给动态映射器。
var dtos = jobs.Select(ie => new JobBO
{
JobId = ie.JobId,
// ... populate remaining DTO fields here.
}).ToList();
getJobResponse.Jobs = dtos;
return getJobResponse;
}
将.ToList()移至末尾会将数据具体化到JobBO DTO / ViewModels中,仅从服务器提取足够的数据以填充所需的行和所需的字段。
在可能有大量数据的情况下,您还应该考虑支持服务器端分页,在其中传递页面编号和页面大小,然后利用.Skip()+ .Take()加载单个一次一页的条目。