尝试更改IQueryable集合的属性

时间:2009-02-10 01:05:26

标签: c# linq linq-to-sql

我正在尝试做我认为简单的事情,但我怀疑我只是太难以知道我可能做错了什么。我有一个LINQ查询返回:

IQueryable<CWords> Result

CWords是我定义如下的类:

public class CWords
{
    public CWords(){}
    public string _column1{ get; set; }
    public float  _column2{ get; set; }

    public void fixData(){}
}

在我的代码中,我试图修改Result的每个成员的_column2字段。我试过了:

foreach (CWords item in Result)
{
    item.fixData();
}

但当然没有用。 item不在适当的范围内,因此我在fixData中所做的任何更改都没有在Result中进行。

由于你无法索引到IQueryable,我的解决方法是执行以下操作:

var items = goodWords.ToList();

for (int i = 0; i < items.Count(); i++ )
   {
    items[i].fixData();
   }

这是正确的方法吗?

2 个答案:

答案 0 :(得分:16)

Brandon,这是使用LINQ时的一个正常错误。请注意,从LINQ返回的IQueryable实际上并不包含您的项目,这就是您无法将其编入索引的原因。当您实际请求项目时,它只有足够的信息来执行查询。这称为“deferred execution”,因为查询不会在您select时执行,但稍后会在您枚举结果时执行。您可以搜索“linq延迟执行”并找到许多人试图解释它是如何工作的。

执行foreach时,查询会运行,您正在按照预期在每个项目上调用fixData()。但是,当您再次访问IQueryable时,您将再次执行查询,并且(取决于您使用的LINQ提供程序),您可能会再次引入原始未修改的项目。

通过调用IQueryable上的ToList(),您将创建一个包含查询所有结果的内存列表。您现在可以索引到此列表并访问它,而无需再次执行查询。如果您可以将所有项目都放在内存中(小结果集),那么使用ToList()可以为您提供良好的解决方案。

@PaulG,你是对的,他可以使用foreach而不是for,但他应该保存对列表的引用,否则他就在他开始的地方(使用IQueryable)。

var items = goodWords.ToList();

foreach (var item in items)
{
    item.fixData();
}

答案 1 :(得分:0)

我相信你的好词是IQueryable<CWords>类型?

为什么不喜欢这个?

foreach (CWords item in goodWords.ToList())
{
    item.fixData();
}