C# 即使生成的SQL很快,实体框架也会随着额外的连接的添加而逐渐变慢
我们有18个表连接,这是典型的ERP系统。连接是通过LINQ over Entity框架完成的 当添加更多联接时,联接将逐渐变慢。返回结果集很小(15条记录)。LINQ生成的查询是通过SQL事件探查器捕获的,当我们通过Microsoft管理控制台运行该查询时,速度非常快:10毫秒。当我们通过C#LINQ over EntityFramework运行它时,需要4秒钟 我猜发生了什么: 将表达式树编译成SQL所需的时间是总共4秒中的2秒,我想还有2秒需要在内部将SQL结果集转换为实际的C#类。此外,它并没有连接到实体框架的初始化,因为我们之前运行过一些查询,对该连接的重复调用会产生相同的4秒钟C# 即使生成的SQL很快,实体框架也会随着额外的连接的添加而逐渐变慢,c#,sql-server,performance,linq,entity-framework,C#,Sql Server,Performance,Linq,Entity Framework,我们有18个表连接,这是典型的ERP系统。连接是通过LINQ over Entity框架完成的 当添加更多联接时,联接将逐渐变慢。返回结果集很小(15条记录)。LINQ生成的查询是通过SQL事件探查器捕获的,当我们通过Microsoft管理控制台运行该查询时,速度非常快:10毫秒。当我们通过C#LINQ over EntityFramework运行它时,需要4秒钟 我猜发生了什么: 将表达式树编译成SQL所需的时间是总共4秒中的2秒,我想还有2秒需要在内部将SQL结果集转换为实际的C#类。此外,
有没有办法加快速度。否则,我们会考虑放弃实体框架,因为它效率非常低……如果不了解您是如何使用linq的,很难判断这里出了什么问题,但我怀疑这会解决您的问题:
var myResult = dataContext.table.Where(x == "Your joins and otherstuff").ToList();
//after converting it to a list use it how you need, but not before.
如果这没有帮助,请发布您的代码。您正确识别了瓶颈。 如果您有非常复杂的查询,我建议您使用编译后的查询来克服表达式树到sql查询的转换 你可以参考 对于第二部分,如果EF使用了两个时间来具体化对象图,那么我建议使用一些其他方法来检索EF之外的数据
一种选择是,您可以使用简洁的sql查询,并且可以使用Dapper(或任何其他小型ORM)直接在具体的模型对象中检索其结果。问题是,您可能正在将其传递给一个数据源,该数据源基于您打开的结果集运行各种附加查询 请尝试以下方法:
IEnumerable<SigmaTEK.Web.Models.SchedulerGridModel> tasks = (from appointment in _appointmentRep.Value.Get().Where(a => (a.Start < DbContext.MaxTime && DbContext.MinTime < a.Expiration))
join timeApplink in _timelineAppointmentLink.Value.Get().Where(a => a.AppointmentId != Guid.Empty)
on appointment.Id equals timeApplink.AppointmentId
join timeline in timelineRep.Value.Get().Where(i => timelines.Contains(i.Id))
on timeApplink.TimelineId equals timeline.Id
join repeater in _appointmentRepeaterRep.Value.Get().Where(repeater => (repeater.Start < DbContext.MaxTime && DbContext.MinTime < repeater.Expiration))
on appointment.Id equals repeater.Appointment
into repeaters
from repeater in repeaters.DefaultIfEmpty()
join aInstance in _appointmentInstanceRep.Value.Get()
on appointment.Id equals aInstance.Appointment
into instances
from instance in instances.DefaultIfEmpty()
join opRes in opResRep.Get()
on instance.ResourceOwner equals opRes.Id
into opResources
from op in opResources.DefaultIfEmpty()
join itemResource in _opDocItemResourcelinkRep.Value.Get()
on op.Id equals itemResource.Resource
into itemsResources
from itemresource in itemsResources.DefaultIfEmpty()
join opDocItem in opDocItemRep.Get()
on itemresource.OpDocItem equals opDocItem.Id
into opDocItems
from opdocitem in opDocItems.DefaultIfEmpty()
join opDocSection in opDocOpSecRep.Get()
on opdocitem.SectionId equals opDocSection.Id
into sections
from section in sections.DefaultIfEmpty()
join opDoc in opDocRep.Get()
on section.InternalOperationalDocument equals opDoc.Id
into opdocs
from opdocitem2 in opDocItems.DefaultIfEmpty()
join opDocItemLink in opDocItemStrRep.Get()
on opdocitem2.Id equals opDocItemLink.Parent
into opDocItemLinks
from link in opDocItemLinks.DefaultIfEmpty()
join finItem in finItemsRep.Get()
on link.Child equals finItem.Id
into temp1
from rd1 in temp1.DefaultIfEmpty()
join sec in finSectionRep.Get()
on rd1.SectionId equals sec.Id
into opdocsections
from finopdocsec in opdocsections.DefaultIfEmpty()
join finopdoc in opDocRep.Get().Where(i => i.DocumentType == "Quote")
on finopdocsec.InternalOperationalDocument equals finopdoc.Id
into finOpdocs
from finOpDoc in finOpdocs.DefaultIfEmpty()
join entry in entryRep.Get()
on rd1.Transaction equals entry.Transaction
into entries
from entry2 in entries.DefaultIfEmpty()
join resproduct in resprosductRep.Get()
on entry2.Id equals resproduct.Entry
into resproductlinks
from resprlink in resproductlinks.DefaultIfEmpty()
join res in resRep.Get()
on resprlink.Resource equals res.Id
into rootResource
from finopdoc in finOpdocs.DefaultIfEmpty()
join rel in orgDocIndRep.Get().Where(i => (i.Relationship == "OrderedBy"))
on finopdoc.Id equals rel.OperationalDocument
into orgDocIndLinks
from orgopdoclink in orgDocIndLinks.DefaultIfEmpty()
join org in orgRep.Get()
on orgopdoclink.Organization equals org.Id
into toorgs
from opdoc in opdocs.DefaultIfEmpty()
from rootresource in rootResource.DefaultIfEmpty()
from toorg in toorgs.DefaultIfEmpty()
select new SigmaTEK.Web.Models.SchedulerGridModel()
{
Id = appointment.Id,
Description = appointment.Description,
End = appointment.Expiration,
Start = appointment.Start,
OperationDisplayId = op.DisplayId,
OperationName = op.Name,
AppContextId = _appContext.Id,
TimelineId = timeline.Id,
AssemblyDisplayId = rootresource.DisplayId,
//Duration = SigmaTEK.Models.App.Utils.StringHelpers.TimeSpanToString((appointment.Expiration - appointment.Start)),
WorkOrder = opdoc.DisplayId,
Organization = toorg.Name
}).Distinct().ToList();
//In your UI
MyGrid.DataSource = tasks;
MyGrid.DataBind();
IEnumerable tasks=(来自_appointrep.Value.Get()中的约会,其中(a=>(a.Starta.AppointmentId!=Guid.Empty)
约会时.Id等于timeApplink.AppointmentId
在timelineep.Value.Get()中加入timeline,其中(i=>timeline.Contains(i.Id))
在timeApplink.TimelineId上等于timeline.Id
将repeater加入到_appointmentRepeaterRep.Value.Get()中,其中(repeater=>(repeater.Startvar result = (from appointment in appointments
from operation in appointment.Operations
where appointment.Id == 12
select new Model {
Id = appointment.Id,
Name = appointment.Name,
// etc, etc
}).ToList();
List<GeographicalLocation> geographicalLocations = new SalesTrackerCRMEntities()
.CreateObjectSet<GeographicalLocation>()
.Where(g => g.Active)
.ToList();
var geographicalLocations = getContext().CreateObjectSet<GeographicalLocation>()
.AsNoTracking()
.Where(g => g.Active).ToList();