我有一个实体,例如,它有另一个实体的外键:
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(未修改)的项的实体。
有什么想法吗?似乎查询是针对数据库启动的,结果实际上是从内存中获取的......
答案 0 :(得分: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
。
如果不是,它会将新实体(具有StateId
10)附加到上下文并将其作为枚举的一部分返回。
因此,您可以获得StateId
10或20的实体组合。基本上,您的查询意味着:“为我提供StateId
10
的所有实体在数据库中。“
通过在查询中附加.AsEnumerable().Where(e => e.StateId == 10)
,您可以过滤掉内存中StateId
10
{/ 1>}的实体。