1

例如,我有一个实体,它具有另一个实体的外键:

public entityA
{
   ....
        [ForeignKey("State")]
        public virtual int StateId { get; set; }
        public virtual States State { get; set; }
   ....
}

IDbSet<entityA> EntitiesA;

StateId 默认初始化为 10。

我将我的上下文初始化为数据库,我总是使用相同的。使用 using 子句初始化后,我会对 EntitiesA 集合中的某些实体进行一些更改(即将 StateId 设置为 20),但我不会使用 context.SaveChanges() 对数据库进行更改,因为此时我不想要。

修改一些实体后,我在我的应用程序中达到了一个点,我执行以下操作:

IQueryable<EntityA> entities = 
                context.EntitiesA.Where(e => e.StateId == 10);
foreach (EntityA _currentEntity in entities)
{
  ....
}

此时,由于我尚未对数据库执行保存更改,因此数据库中的实体继续将其状态设为 10(而不是修改后的 20),因此满足条件 e.StateId == 10 但实体包含 StateId 为 20 的项目,所以我不明白这个……

期望的行为是条件 e.StateId 不满足那些先前已修改为 20 的实体以及仅包含那些 stateid 仍为 10(未修改)的项目的实体。

有任何想法吗?似乎查询是针对数据库启动的,实际上结果是从内存中获取的......

4

1 回答 1

1

这种行为是意料之中的,但是是的,这令人困惑。为了解决这个问题,你必须运行一个看起来很奇怪的查询,例如:

IEnumerable<EntityA> entities = context.EntitiesA
    .Where(e => e.StateId == 10)  // LINQ-to-Entities = filter in database
    .AsEnumerable()
    .Where(e => e.StateId == 10); // LINQ-to-Objects = filter in memory

foreach (EntityA _currentEntity in entities)
{
    ....
}

发生的情况是您的查询检索StateId数据库中 = 10 的实体。返回结果时,EF 会遍历所有加载的行并检查是否已将具有相同键的实体附加到上下文。

  • 如果是,它会在枚举中返回这个附加的实体以及它当前在内存中的所有值。默认情况下,EF 不会更新加载行中的值,因此StateId您修改的实体的 仍然是20.

  • 如果不是,它将新实体(具有StateId10 个)附加到上下文并将其作为枚举的一部分返回。

结果,您得到了具有 10 或 20 个实体的组合。基本上,您的查询意味着:“给我所有在数据库StateId中具有StateIdof的实体。”10

通过附加到查询中,您可以过滤掉内存.AsEnumerable().Where(e => e.StateId == 10)中具有StateIdof的实体。10

于 2013-06-25T20:59:15.480 回答