我使用EF6,当我尝试选择相当大量的对象(大约1000)时,性能非常糟糕。我能做些什么来提高性能吗?我正在使用Lazy Loading。
我已经考虑过修改查询,只选择我需要的特定功能字段,或者选择一个匿名类型并返回它,只有在实际需要时才选择进入BI.Lead对象。我只是不明白这会对性能产生什么影响。据我所知,延迟加载应该在请求属性之前不执行返回属性的查询吗?
示例代码
Dim db As New EFDB.EFDBContainer
Dim one As IQueryable(Of EFDB.Lead) = db.Leads.AsNoTracking.Where(Function(c) c.ClientID = ClientID And c.softDelete = False And c.State = ParamState).OrderBy(Function(c) c.DateCreate())
Dim two As List(Of EFDB.Lead) = one.ToList()
Dim three As IEnumerable(Of BI.Lead) = two.Select(Function(p) New BI.Lead(p, db))
Return three.ToList
myDataRepeater.Datasource = three.Tolist()
myDataRepeater.Databind()
请注意,我必须选择EF对象结果到 BI.Lead对象中;因为调用者期望BI.Lead对象列表。通过将现有的DB上下文传递给select函数,我已经显着提高了性能。
BI.Lead
Public Sub New()
_cxt = New EFDB.EFDBContainer
_person = New EFDB.Lead
End Sub
Public Sub New(EntityObject As EFDB.Lead, cxt As EFDB.EFDBContainer)
_person = EntityObject
_cxt = cxt
End Sub
Public Sub New(ID As Guid)
If Not IsNothing(ID) Then
If IsNothing(_cxt) Then _cxt = New EFDB.EFDBContainer
If IsNothing(_person) Then
_person = _cxt.Leads.Find(ID)
End If
End If
End Sub
Public Sub New(ID As Guid)
If Not IsNothing(ID) Then
If IsNothing(_cxt) Then _cxt = New EFDB.EFDBContainer
If IsNothing(_person) Then
_person = _cxt.Leads.Find(ID)
End If
End If
End Sub
Private _cxt As EFDB.EFDBContainer
Private _person As EFDB.Lead
Protected Overridable Overloads Sub Dispose(disposing As Boolean)
If disposing Then
If Not IsNothing(_cxt) Then
_cxt.SaveChanges()
_cxt.Dispose()
_person = Nothing
End If
End If
End Sub
Public Overloads Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Public ReadOnly Property AppointmentDate As Date?
Get
If _person.Appointments.Count() < 1 Then Return Nothing
Dim _apt = _person.Appointments.FirstOrDefault()
If Not IsNothing(_apt) Then Return _apt.AppointmentDate
Return Nothing
End Get
End Property
Public Property EmailAddress As String
Get
If Not IsNothing(_person.EmailAddress) Then
Return _person.EmailAddress
Else
Return String.Empty
End If
End Get
Set(value As String)
If Not IsNothing(_person) Then
_person.EmailAddress = value
End If
End Set
End Property
返回第一个.ToList()只需要5-10秒就有1500条记录。
返回接下来的三个.ToList()大约需要20-30秒,记录相同。
最后,数据绑定在25-30秒时间最长,记录相同。
在datarepeater中,我直接转换container.dataItem以尝试提高性能。我知道Eval()会带来巨大的性能损失。它这样做是因为我需要在javascript中提取一些值。有更好的方法吗?
<%# DirectCast(Container.DataItem, BI.Lead).ID%>