我有一个数据上下文(创建一次),我使用它多次获取相同的数据库记录,例如,我获得指定相同产品 ID 的相同产品记录。
比方说,每次我调用时context.Products.Single(p => p.ProdID == 1)
,上下文都会返回产品实体的相同实例,但每次都查询数据库,这在 SQL Server Profiler 中可见。
我通过修改调用之间的一些属性来检查它是否返回相同的实例。下一个调用返回具有修改后属性的实例。
为什么它每次都查询数据库,有没有办法避免这种情况?
我有一个数据上下文(创建一次),我使用它多次获取相同的数据库记录,例如,我获得指定相同产品 ID 的相同产品记录。
比方说,每次我调用时context.Products.Single(p => p.ProdID == 1)
,上下文都会返回产品实体的相同实例,但每次都查询数据库,这在 SQL Server Profiler 中可见。
我通过修改调用之间的一些属性来检查它是否返回相同的实例。下一个调用返回具有修改后属性的实例。
为什么它每次都查询数据库,有没有办法避免这种情况?
这样做是因为另一个用户可能在第一次和第二次通话之间修改了记录。
如果数据相对静态,请考虑缓存解决方案。
您可以使用ObjectContext.GetObjectByKey ( DbSet<T>.Find
for DbContext
) 通过其键查询实体。此方法将检查具有指定键的对象是否已附加到上下文。如果是,它将返回该对象而不查询数据库。如果它在上下文中不存在,它将运行数据库查询。
LINQ 查询通常查询数据库,无论对象是否已附加到上下文。EF 无法预先知道是否附加了对象,因为它不知道查询的结果。您的 LINQ 按键查询是一个例外 - 理论上 - 因为 EF可以知道查询是否必要,因为它可以检查具有该键的对象是否已附加。但是这个异常并没有被这样处理——这就是GetObjectByKey
存在的原因——它像所有其他 LINQ 查询一样查询数据库。
查询结果会发生什么由 ObjectSet 的MergeOption 决定。默认情况下AppendOnly
,如果带有键的对象已附加到上下文,则丢弃查询结果。查询不会覆盖或刷新任何内容。仅当上下文中不存在具有键的对象时,查询结果中的对象才会具体化并将附加到上下文中。您可以通过选择另一个来更改此默认行为MergeOption
。