Попытка изменить свойства коллекции IQueryable - PullRequest
9 голосов
/ 10 февраля 2009

Я пытаюсь сделать то, что я думаю, что-то простое, но я подозреваю, что я просто слишком n00b, чтобы понять, что я, вероятно, делаю что-то неправильно У меня есть запрос возврата LINQ:

IQueryable<CWords> Result

Где CWords - это класс, который я определил следующим образом:

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

    public void fixData(){}
}

в моем коде я пытаюсь изменить поле _column2 для каждого члена Result. Я попробовал:

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

Но, конечно, это не сработало. Элемент не находится в нужной области, поэтому любые изменения, которые я вносил в fixData, не принимались в результате.

Поскольку вы не можете индексировать в IQueryable, я исправил это следующим образом:

var items = goodWords.ToList();

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

Это правильный способ сделать это?

Ответы [ 2 ]

16 голосов
/ 10 февраля 2009

Брэндон, это нормальная ошибка при использовании LINQ. Видите ли, IQueryable, возвращаемый из LINQ, на самом деле не содержит ваши элементы, поэтому вы не можете индексировать его. У него достаточно информации только для выполнения запроса, когда вы фактически запрашиваете элементы. Это называется " отложенное выполнение ", потому что запрос выполняется не при select, а позже, когда вы перечисляете результаты. Вы можете найти «отложенное выполнение linq» и найти множество людей, пытающихся объяснить, как это работает.

Когда вы делаете foreach, запрос запускается, и вы вызываете fixData () для каждого элемента, как вы и предполагали. Однако, когда вы снова получите доступ к IQueryable, вы выполните запрос во второй раз, и (в зависимости от используемого поставщика LINQ) вы можете ввести исходные неизмененные элементы во второй раз.

Вызывая ToList () в IQueryable, вы создаете список в памяти со всеми результатами запроса. Теперь вы можете индексировать этот список и получать к нему доступ по своему усмотрению без повторного выполнения запроса. Если у вас все в порядке с наличием всех элементов в памяти (небольшой набор результатов), то использование ToList () может быть хорошим решением для вас.

@ PaulG, вы правы в том, что он может использовать foreach вместо for, но ему следует сохранить ссылку на список, иначе он окажется там, где начал (с IQueryable).

var items = goodWords.ToList();

foreach (var item in items)
{
    item.fixData();
}
0 голосов
/ 10 февраля 2009

Я считаю, что ваши добрые слова IQueryable<CWords> типа?

Так почему бы не так?

foreach (CWords item in goodWords.ToList())
{
    item.fixData();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...