DbSet.Find方法可笑缓慢相比.SingleOrDefault上ID(DbSet.Find m

2019-06-17 13:43发布

我有以下代码(数据库是SQL Server精简4.0):

Dim competitor=context.Competitors.Find(id)

当我资料这个查找方法需要300个+ MS从刚刚60的记录表中​​检索竞争对手。

当我改变的代码:

Dim competitor=context.Competitors.SingleOrDefault(function(c) c.ID=id)

然后竞赛者在短短的3毫秒中。

竞争对手类:

Public Class Competitor
    Implements IEquatable(Of Competitor)

    Public Sub New()
        CompetitionSubscriptions = New List(Of CompetitionSubscription)
        OpponentMeetings = New List(Of Meeting)
        GUID = GUID.NewGuid
    End Sub

    Public Sub New(name As String)
        Me.New()
        Me.Name = name
    End Sub

    'ID'
    Public Property ID As Long
    Public Property GUID As Guid

    'NATIVE PROPERTIES'
    Public Property Name As String

    'NAVIGATION PROPERTIES'
    Public Overridable Property CompetitionSubscriptions As ICollection(Of CompetitionSubscription)
    Public Overridable Property OpponentMeetings As ICollection(Of Meeting)
End Class

我定义了许多为许多关系CompetitionSubscriptionsOpponentMeetings使用流利的API。

该ID属性Competitor类是由代码首先翻译成标识列在数据表(SQL Server精简4.0)主键的龙

这里发生了什么??

Answer 1:

Find电话DetectChanges内部, SingleOrDefault (或通常的任何查询)没有。 DetectChanges是一个昂贵的操作,所以这就是为什么的原因Find慢(但如果实体已经被加载到上下文,因为它可能会变得更快Find不会运行查询,但只返回加载的实体)。

如果你想使用Find了很多实体-在例如一个循环-你可以禁用自动变化检测,像这样(不能写在VB,所以C#示例):

try
{
    context.Configuration.AutoDetectChangesEnabled = false;
    foreach (var id in someIdCollection)
    {
        var competitor = context.Competitors.Find(id);
        // ...
    }
}
finally
{
    context.Configuration.AutoDetectChangesEnabled = true;
}

现在, Find不会叫DetectChanges与每一个电话,它应该是一样快SingleOrDefault (如果实体已经被附加到上下文和更快)。

自动变化检测是一个复杂而有点神秘主题。 一个伟大的详细讨论可以在这个由四部分组成的系列中找到:

(连结至第1部分,所述链接部件2,3和4是在该文章的开头)

http://blog.oneunicorn.com/2012/03/10/secrets-of-detectchanges-part-1-what-does-detectchanges-do/



文章来源: DbSet.Find method ridiculously slow compared to .SingleOrDefault on ID