C# Linq在select语句中调用方法的速度非常慢
我试图找出是否有一种方法可以从我的linq select语句中调用一个方法来构建一个不会显著降低速度的对象列表。这背后的原因是,我还希望在尝试仅获取其中一个对象时调用相同的方法,并且不希望必须维护两个版本,即,如果我在对象中添加了另一个字段,或者希望以不同的方式呈现其中一个字段,我将不必在多个位置对其进行更改 在下面的示例中,测试1的运行速度比测试2快100倍以上:C# Linq在select语句中调用方法的速度非常慢,c#,linq,C#,Linq,我试图找出是否有一种方法可以从我的linq select语句中调用一个方法来构建一个不会显著降低速度的对象列表。这背后的原因是,我还希望在尝试仅获取其中一个对象时调用相同的方法,并且不希望必须维护两个版本,即,如果我在对象中添加了另一个字段,或者希望以不同的方式呈现其中一个字段,我将不必在多个位置对其进行更改 在下面的示例中,测试1的运行速度比测试2快100倍以上: // Start timer var timer = new Stopwatch(); timer.Start(); var t
// 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/>";
这是因为我希望能够调用GetJobDetails返回单个作业,例如:
public JobExtended GetJobDetails(int jobId)
{
using (DataContext dc = new DataContext())
{
return dc.Jobs.Where(x => x.jobId == jobId).Select(j => GetJobDetails(j)).FirstOrDefault();
}
}
如果我决定添加一个新的字段来更改Url值的生成方式,那么这样做只允许我更新GetJobDetails方法,但是这样做要慢得多。有没有办法解决这个问题,我已经尝试了以下似乎没有帮助的方法:
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();
我以前见过这种问题。如果我还记得的话,我们所做的就是将查询叠加起来
public IEnumerable<JobExtended> ConvertToJobExtended(IEnumerable<Job> jobs)
{
return
from job in jobs
select new JobExtended()
{
MyString = job.MyInt.ToString(),
...
};
}
从这里可以有很多选择。。。我希望这是您希望做的事情的正确方向。原因测试1更快,因为查询在服务器上执行一次,并且只返回所选字段
var test = (from job in dc.Jobs
where !job.archived
select new JobExtended()
{
JobId = job.jobId,
NodeId = job.nodeId,
...
}).ToList();
当您在测试2中调用GetJobDetails时,需要首先具体化参数j,然后才能将其作为参数发送给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,
...
}
}
JobExtended的构造函数应该只接受一个参数,即Data.Job。分配属性和检查其他内容应该在构造函数内部完成。我这么说是因为你有很多财产。您的代码将减少为返回新的JobExtendedjob;。。。。你在一行中做的太多了。这就是我想说的。@m.kazemAkhgary您的解决方案是将JobExtended类型构造函数与Job类型紧密耦合,这可能是不可取的。我尝试了这个方法,但它似乎根本没有改善性能。您使用的是IEnumerable还是IQueryable?另外,请注意,最后只调用了一次ToList。我尝试了此操作,但在SelectJobExtended方法中收到以下错误:其他信息:无法将表达式“TableJob.Wherex=>Notx.archived”转换为SQL,并且无法将其视为本地表达式。它应该是。Selectjob=>new JobExtended。。。{ .. };IList应该是IEnumerable。我已经更新了答案。我使用这个方法工作,我的问题是我在SelectJobExtended方法中使用了String.IsNullOrEmpty。
return dc.Jobs.Where(x => x.jobId == jobId).Select(j => GetJobDetails(j)).FirstOrDefault();
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();