2012-02-21 56 views
0

说我有IQueryable<Car> cars推迟执行值不变

我重复它,例如:

foreach (Car c in cars) 
{ 
    c.Doors = 2; 
} 

为什么c.Doors包含,而不是更改后的值在foreach后的原始值,?

预先感谢您

+0

我知道如果在枚举之前将它转换为列表,我会得到正确的结果。 – Dante 2012-02-21 13:14:00

+0

IQueryable 的实现或者在每次迭代中生成一个新集合,或者Car.Doors的setter被“破坏”。请向我们展示IQuerable 的创建位置 – Polity 2012-02-21 13:16:32

+0

IQueryable 是Linq to Entities查询的结果。 setter很好,因为在Linq查询中,我可以将值分配给属性Doors。 – Dante 2012-02-21 13:21:02

回答

1

您表示IQueryable的是LINQ到实体查询这是不正确的语句的结果。 MyDatabaseContext.Cars.Where(x => x.Name ==“Test”)返回一个IQueryable,它在迭代过程中对数据库执行查询。 (迭代是当你对它进行foreach时)。所以它不包含结果集,只是查询。

在汽车上循环两次会生成2个相同的数据库查询并返回2个相同的结果集。如果你想保存数据。您需要调用ToArray或ToList或在操作之后,在再次迭代之前执行更改的保存。

+0

也许这是我的错误措辞,但我知道IQueryable本身并不执行查询。所以,当我迭代它时,查询被执行一次。如果我在迭代之后执行ToList(),则查询将再次执行。对? – Dante 2012-02-21 13:30:37

+0

正确,ToList内部迭代源以及:) – Polity 2012-02-21 13:35:49

1

IQueryable进行迭代从数据库中检索结果集,因为我相信你知道。我在这个和其他情况下观察到的结果是没有被缓存,所以你经常会发现再次遍历IQueryable会再次运行查询,因此你的修改不会被保留,因为你得到了一个新的结果集从未受到该代码的影响。

,当你调用ToList()第一和迭代的,其结果它工作的原因是因为ToList()检索和物化整个结果集,然后将其不再链接到数据库的内容实际上只是一个副本是什么数据库返回。

要确保您的更改将坚持的唯一方法是对本地数据进行操作,即将其从IQueryable土地中提取出来。这可以像保存结果集的IEnumerable(即ToEnumerable()的结果)一样简单,每次枚举它时将返回相同的结果集,但与ToList()不同,它不会立即导致评估。