与 ID 上的 .SingleOrDefault 相比,DbSet.Find 方法慢得离谱

2024-01-11

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

Dim competitor=context.Competitors.Find(id)

当我对此进行分析时,Find 方法需要 300+ 毫秒才能从只有 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

我定义了多对多关系CompetitionSubscriptions and OpponentMeetings使用流畅的 API。

的 ID 属性Competitorclass 是一个 Long,由 Code First 转换为数据表中具有主键的 Identity 列 (SQL Server Compact 4.0)

这里发生了什么??


Find calls 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;
}

Now, Find不会打电话DetectChanges每次通话的速度应该尽可能快SingleOrDefault(如果实体已经附加到上下文,则速度更快)。

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

(第 1 部分的链接,第 2、3 和 4 部分的链接位于该文章的开头)

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

与 ID 上的 .SingleOrDefault 相比,DbSet.Find 方法慢得离谱 的相关文章

随机推荐