Linq调用select语句中的方法非常慢
问题描述:
我想要找到是否有方法从我的linq select语句中调用一个方法来构建一个不会显着减慢速度的对象列表。这背后的原因是我也想调用相同的方法,当试图获得只有一个对象,并不想保持两个版本(即如果我有另一个字段添加到对象或想呈现其中之一不同的领域,我不会改变它在多个地方)。Linq调用select语句中的方法非常慢
// Start timer
var timer = new Stopwatch();
timer.Start();
var test = (from job in dc.Jobs
where !job.archived
select new JobExtended()
{
JobId = job.jobId,
NodeId = job.nodeId,
JobName = job.name != string.Empty ? job.name : "TBC",
Salary = job.salary,
RecruiterId = job.fkRecruiterId,
RecruiterNodeId = job.JobRecruiter != null ? job.JobRecruiter.recruiterNodeId : null,
RecruiterName = job.JobRecruiter != null ? job.JobRecruiter.name : string.Empty,
LocationId = job.fkLocationId,
Location = job.refJobLocation != null ? job.refJobLocation.jobLocation : "",
ContractTypeId = job.fkContractTypeId,
ContractType = job.refJobContractType != null ? job.refJobContractType.contractType : "",
CategoryId = job.fkCategoryId,
Category = job.refJobCategory != null ? job.refJobCategory.category : "",
ClosingDate = job.closingDate,
Featured = job.featured,
JobOfTheWeek = job.jobOfTheWeek,
PublishedDate = job.publishedDate,
Url = "/jobs/" + job.name.Replace(" ", "-").Replace("&", "and").Replace("'", "") + (job.fkLocationId.HasValue ? "-in-" + job.refJobLocation.jobLocation.Replace(" ", "-").Replace("&", "and").Replace("'", "") : "") + "-jn" + job.jobId,
CreatedOn = job.createdOnDate,
PrintWidth = job.printWidth,
PrintHeight = job.printHeight,
UntilFilled = (job.untilFilled != null && job.untilFilled.Value),
AdvertCost = job.advertCost,
DatesToShow = job.relJobDates.Where(x => x.fkJobId == job.jobId).Select(x => x.date).ToList(),
IsParentJob = job.relLinkedJobs != null && job.relLinkedJobs.Any(x => x.fkParentJobId == job.jobId),
IsAlternateWeekJob = job.alternateWeek != null && job.alternateWeek.Value,
Archived = job.archived,
LastModifiedDate = job.lastModifiedDate,
RecruiterContactDetails = job.recruiterContactDetails
}).ToList();
// Stop timer
timer.Stop();
// Output info
litTest.Text = "TEST 1 in " + timer.Elapsed.TotalSeconds + " seconds<br/>";
//Start timer
timer = new Stopwatch();
timer.Start();
var test2 = (from job in dc.Jobs
where !job.archived
select GetJobDetails(job)).ToList();
//Stop timer
timer.Stop();
//Output info
litTest.Text += "TEST 2 in " + timer.Elapsed.TotalSeconds + " seconds<br/>";
这是测试2正在呼叫应当创建了在TEST 1被返回的相同对象的方法:比试验2更快
在下面的例子中,TEST 1个行驶超过100倍:
public static JobExtended GetJobDetails(Data.Job job)
{
return new JobExtended()
{
JobId = job.jobId,
NodeId = job.nodeId,
JobName = job.name != string.Empty ? job.name : "TBC",
Salary = job.salary,
RecruiterId = job.fkRecruiterId,
RecruiterNodeId = job.JobRecruiter != null ? job.JobRecruiter.recruiterNodeId : null,
RecruiterName = job.JobRecruiter != null ? job.JobRecruiter.name : string.Empty,
LocationId = job.fkLocationId,
Location = job.refJobLocation != null ? job.refJobLocation.jobLocation : "",
ContractTypeId = job.fkContractTypeId,
ContractType = job.refJobContractType != null ? job.refJobContractType.contractType : "",
CategoryId = job.fkCategoryId,
Category = job.refJobCategory != null ? job.refJobCategory.category : "",
ClosingDate = job.closingDate,
Featured = job.featured,
JobOfTheWeek = job.jobOfTheWeek,
PublishedDate = job.publishedDate,
Url = "/jobs/" + job.name.Replace(" ", "-").Replace("&", "and").Replace("'", "") + (job.fkLocationId.HasValue ? "-in-" + job.refJobLocation.jobLocation.Replace(" ", "-").Replace("&", "and").Replace("'", "") : "") + "-jn" + job.jobId,
CreatedOn = job.createdOnDate,
PrintWidth = job.printWidth,
PrintHeight = job.printHeight,
UntilFilled = (job.untilFilled != null && job.untilFilled.Value),
AdvertCost = job.advertCost,
DatesToShow = job.relJobDates.Where(x => x.fkJobId == job.jobId).Select(x => x.date).ToList(),
IsParentJob = job.relLinkedJobs != null && job.relLinkedJobs.Any(x => x.fkParentJobId == job.jobId),
IsAlternateWeekJob = job.alternateWeek != null && job.alternateWeek.Value,
Archived = job.archived,
LastModifiedDate = job.lastModifiedDate,
RecruiterContactDetails = job.recruiterContactDetails
};
}
这样做的原因是因为我希望能够调用“GetJobDetails”例如用于返回一个作业:
public JobExtended GetJobDetails(int jobId)
{
using (DataContext dc = new DataContext())
{
return dc.Jobs.Where(x => x.jobId == jobId).Select(j => GetJobDetails(j)).FirstOrDefault();
}
}
这样做会让我只需要更新“GetJobDetails”方法,例如,如果我决定添加一个新的变化字段,如何生成“Url”值,但这样做的速度会慢很多。有没有解决的办法,我已经尝试过这似乎并没有帮助的情况如下:我以前见过这种问题
var test3 = (from job in dc.Jobs
where !job.archived
select job).AsEnumerable()
.Select(GetJobDetails).ToList();
var test4 = (from job in dc.Jobs
where !job.archived
select GetJobDetails(job));
var test4a = test4.ToList();
答
测试1的速度较快,原因是查询在服务器上执行一次,只返回选定的字段。
var test = (from job in dc.Jobs
where !job.archived
select new JobExtended()
{
JobId = job.jobId,
NodeId = job.nodeId,
...
}).ToList();
当你调用TEST 2参数j需要GetJobDetails首先被物化,才能发送作为参数传递给GetJobDetails。所以有多个完整对象的调用。
return dc.Jobs.Where(x => x.jobId == jobId).Select(j => GetJobDetails(j)).FirstOrDefault();
为了达到像你想要的东西,你应该使用扩展方法。这个扩展了IQueryable。
public static IEnumerable<JobExtended> SelectJobExtended(this IQueryable<Data.Job> query)
{
return query
.Select(o => new JobExtended()
{
JobId = job.jobId,
NodeId = job.nodeId,
...
}
}
然后,您可以拨打:
dc.Jobs.Where(x => x.jobId == jobId).SelectJobExtended().FirstOrDefault();
答
。如果我记得,我们所做的是“堆积”查询。
public IEnumerable<JobExtended> ConvertToJobExtended(IEnumerable<Job> jobs)
{
return
from job in jobs
select new JobExtended()
{
MyString = job.MyInt.ToString(),
...
};
}
你可以做那么什么是调用它的方式如下:
var query = (from job in dc.Jobs
where !job.archived
select job;
var test2 = ConvertToJobExtended(query).ToList();
有很多替代品,可以从这里去...我希望这正好在你的正确方向正在寻找。
JobExtended'的'构造函数应该只有一个参数,这就是'Data.Job'。分配属性和检查其他东西应该在构造函数内完成。我说这是因为你有很多属性。你的代码将被缩减为'返回新的JobExtended(工作);'....你在一行中做得太多了。这就是我想说的。 –
@ M.kazemAkhgary您的解决方案将JobExtended类型构造函数与Job类型紧密耦合,这可能不合意。 – Svek