以下是我的思考过程:
假设您进行以下查询操作:
SiteUser someUser = context.SiteUser.Where(role => role.UserID == 1).ToList()[0];
这只是一个简单的示例,意思是我想从ID为1的表中获取一个用户。现在假设这是第一次查询,那么我猜测它必须在上下文中创建SiteUser列表,查询数据库,然后填充它的列表。使用分析器,我看到了这个结果:SELECT
[Extent1].[UserID] AS [UserID],
[Extent1].[MainEmail] AS [MainEmail],
[Extent1].[Password] AS [Password],
[Extent1].[UserName] AS [UserName]
FROM [TIDBA].[TI_USER] AS [Extent1]
WHERE 1 = [Extent1].[UserID]
很好。它做到了我所期望的,并且在SiteUser列表中(如果我使用Watch深入挖掘),我可以看到上下文SiteUser列表中有一个项目,恰好是表示此数据行的水化对象。
接下来,我想修改一些内容,但不保存:
someUser.UserName = "HIHIHI";
现在假设由于某种原因我想再次使用相同的上下文来获取它(这是一个奇怪的例子,但实际上是为了证明这个情况确实发生了):
someUser = context.SiteUser.Where(role => role.UserID == 1).ToList()[0];
我认为会发生的情况是它会查看上下文中的SiteUser列表,因为生成的属性是这样说的。(如果不为空,则返回列表)然后它会查看是否存在并返回。没有数据库访问。猜猜分析器说了什么...
SELECT
[Extent1].[UserID] AS [UserID],
[Extent1].[MainEmail] AS [MainEmail],
[Extent1].[Password] AS [Password],
[Extent1].[UserName] AS [UserName]
FROM [TIDBA].[TI_USER] AS [Extent1]
WHERE 1 = [Extent1].[UserID]
嗯,我开始考虑也许这是一个肠胃检查,以查看该数据项上是否有任何更改,并仅在客户端未更改的值上更新SiteUser对象。(有点像context.Refresh(RefreshMode.ClientWins, context.SiteUser))。因此,我将其停止在:
someUser = context.SiteUser.Where(role => role.UserID == 1).ToList()[0];
我在数据库中更改了一个值(密码列),并让它命中数据库。但是对象上没有任何变化。
这里似乎有些不对劲。它命中数据库以选择我已经在上下文中填充的对象,但它不应用我在数据库中手动进行的更改。那么它为什么还要命中数据库呢?
更新 在下面一些链接的帮助下,我能够深入挖掘并找到了以下内容:
看起来有一个枚举设置告诉如何处理负载。现在在阅读后,我看到了MergeOption.AppendOnly的相关信息:
已存在于对象上下文中的对象不会从数据源加载。这是查询或在EntityCollection<(Of <(TEntity>)>)上调用Load方法时的默认行为。
这表明如果我在上下文中拥有它,则不应该命中数据库。然而,这似乎并不正确。如果OverwriteChanges或PreserveChanges是默认设置,那就有意义了,但它们不是。这似乎与应该发生的情况相矛盾。我能想到的唯一一件事就是“已加载”的意思只是没有覆盖。然而,这并不意味着没有查询到数据库。