Linq对象不是“持久”变化

时间:2011-05-24 12:29:07

标签: linq linq-to-objects

我正在使用linq通过外观对象通过Id选择一堆对象。此Facade有一个函数GetObjectById(string id),它返回一个MyObject。我根据id列表在一个查询中选择了一堆对象:

IEnumerable<MyObject> objects = 
   from id in ids   
   select facade.GetObjectById(id);

然后我在我的对象上设置了一些值,如下所示:

foreach(MyObject object in objects)
{
  object.someValue = "banaan";
}

稍后当我检查对象IEnumerable时,someValue未设置为“banaan”。

看起来它与linq的延迟执行有关,因为当我将.ToList()置于第一个查询后面时, 工作。但是,我认为我应该可以做这样的事情。我在这做错了什么?或者我对你应该如何使用linq的理解是错误的?

提前致谢。

3 个答案:

答案 0 :(得分:2)

确定是延迟执行的问题。如果再次执行查询,它将再次调用facade方法,如果facade方法从某处加载数据(=创建新实例),则以前的更改将丢失。您的foreach是第一次执行,第一次foreach之外的检查是第二次执行。

如果您想在这种情况下对相同的实例进行操作,则必须调用ToList

答案 1 :(得分:1)

第二次检查对象时,是否重新评估objects可枚举对象?因为这会使它再次调用facade.GetObjectById(id)。

尝试实现可枚举的实现。像这样:

IEnumerable<MyObject> objects = 
    (from id in ids 
     select facade.GetObjectById(id)).ToArray();

答案 2 :(得分:0)

我假设您在某个地方运行SQL服务器,数据来自何处?

查询将保留在LINQ to SQL空间中,直到如前两个答案中所建议的那样,您调用ToList()或ToArray()或类似命令。只有这样它才真正成为LINQ to Object,并且是实例化的数据,并且会在程序的内存空间中持续存在。

通过这种方式,在更改列表后,您可以再次执行相同的查询,并获得一个不同的列表,其中没有您的更改。

以下可能有更好的解释:

(from id in ids select facade.GetObjectById(id)).Where(o=>string.IsNullOrEmpty(o.Name))

这会产生错误,因为没有从string.IsNullOrEmpty到SQL的转换。

(from id in ids select facade.GetObjectById(id)).ToList().Where(o=>string.IsNullOrEmpty(o.Name))

这不会产生错误,因为在ToList()之后你处于对象空间。