在选择大量相关对象时改善实体框架性能?

时间:2016-10-08 16:29:03

标签: vb.net performance entity-framework

我使用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%>

0 个答案:

没有答案