与 ID 上的 .SingleOrDefault 相比,DbSet.Find 方法慢得可笑 [英] DbSet.Find method ridiculously slow compared to .SingleOrDefault on ID

查看:30
本文介绍了与 ID 上的 .SingleOrDefault 相比,DbSet.Find 方法慢得可笑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have the following code (Database is SQL Server Compact 4.0):

Dim competitor=context.Competitors.Find(id)

当我对此进行分析时,Find 方法需要 300 多毫秒才能从只有 60 条记录的表中检索竞争对手.

When I profile this the Find method takes 300+ms to retrieve the competitor from a table of just 60 records.

当我将代码更改为:

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

然后在短短 3 毫秒内找到竞争对手.

Then the competitor is found in just 3 ms.

竞争者类:

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

我使用 fluent API 为 CompetitionSubscriptionsOpponentMeetings 定义了多对多关系.

I defined the many to many relations for CompetitionSubscriptions and OpponentMeetings using the fluent API.

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

The ID property of the Competitor class is a Long which is translated by Code First to an Identity column with a primary key in the datatable (SQL Server Compact 4.0)

这是怎么回事??

推荐答案

Find 在内部调用 DetectChangesSingleOrDefault(或通常的任何查询)没有.DetectChanges 是一个昂贵的操作,所以这就是 Find 较慢的原因(但如果实体已经加载到上下文中,它可能会变得更快,因为 Find 不会运行查询,而只会返回加载的实体).

Find calls DetectChanges internally, SingleOrDefault (or generally any query) doesn't. DetectChanges is an expensive operation, so that's the reason why Find is slower (but it might become faster if the entity is already loaded into the context because Find would not run a query but just return the loaded entity).

如果您想对很多实体使用 Find - 例如在循环中 - 您可以像这样禁用自动更改检测(不能在 VB 中编写,所以是 C# 示例):

If you want to use Find for a lot of entities - in a loop for example - you can disable automatic change detection like so (can't write it in VB, so a C# example):

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

现在,Find 不会在每次调用时都调用 DetectChanges,它应该和 SingleOrDefault 一样快(如果实体是已经附加到上下文).

Now, Find won't call DetectChanges with every call and it should be as fast as SingleOrDefault (and faster if the entity is already attached to the context).

自动更改检测是一个复杂且有点神秘的主题.在这个由四部分组成的系列中可以找到非常详细的讨论:

Automatic change detection is a complex and somewhat mysterious subject. A great detailed discussion can be found in this four-part series:

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

(Link to part 1, the links to parts 2, 3 and 4 are at the beginning of that article)

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

这篇关于与 ID 上的 .SingleOrDefault 相比,DbSet.Find 方法慢得可笑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆