我有以下代码(数据库是SQL Server Compact 4.0):
Dim competitor=context.Competitors.Find(id)
当我对此进行分析时,Find方法需要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
我使用流畅的API为CompetitionSubscriptions
和OpponentMeetings
定义了多对多的关系。
Competitor
类的ID属性是Long,它由Code First转换为带有数据表中主键的Identity列(SQL Server Compact 4.0)
这里发生了什么?
答案 0 :(得分:55)
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/