35

我有以下代码(数据库是 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我为和OpponentMeetings使用 fluent API定义了多对多关系。

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

这里发生了什么??

4

1 回答 1

58

Find内部调用DetectChangesSingleOrDefault(或通常任何查询)没有。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/

于 2012-07-27T12:54:52.730 回答