Dab*_*rnl 34 entity-framework ef-code-first sql-server-ce-4 dbcontext dbset
我有以下代码(数据库是SQL Server Compact 4.0):
Dim competitor=context.Competitors.Find(id)
Run Code Online (Sandbox Code Playgroud)
当我对此进行分析时,Find方法需要300 + ms才能从仅有60条记录的表中检索竞争对手.
当我将代码更改为:
Dim competitor=context.Competitors.SingleOrDefault(function(c) c.ID=id)
Run Code Online (Sandbox Code Playgroud)
然后在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
Run Code Online (Sandbox Code Playgroud)
我定义了多个关系CompetitionSubscriptions并OpponentMeetings使用了流畅的API.
Competitor该类的ID属性是一个Long,由Code First转换为一个Identity列,在数据表中有一个主键(SQL Server Compact 4.0)
这里发生了什么??
Sla*_*uma 55
FindDetectChanges内部调用,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;
}
Run Code Online (Sandbox Code Playgroud)
现在,Find不会调用DetectChanges每个调用,它应该尽可能快SingleOrDefault(如果实体已经附加到上下文,则更快).
自动变化检测是一个复杂而有些神秘的主题.在这个由四部分组成的系列中可以找到一个非常详细的讨论:
(链接到第1部分,第2,3和4部分的链接位于该文章的开头)
http://blog.oneunicorn.com/2012/03/10/secrets-of-detectchanges-part-1-what-does-detectchanges-do/