Linq к объектам не "сохраняющиеся" изменения - PullRequest
1 голос
/ 24 мая 2011

Я использую linq для выбора группы объектов по идентификатору через фасадный объект.Этот фасад имеет функцию GetObjectById(string id), которая возвращает MyObject.Я выбираю группу объектов в одном запросе на основе списка идентификаторов:

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 ]

2 голосов
/ 24 мая 2011

Конечно, это проблема отложенного исполнения. Если запрос будет выполнен снова, он снова вызовет ваш метод фасадов, и если метод фасадов загружает данные откуда-то (= создает новые экземпляры), ваши прежние изменения будут потеряны. Ваше foreach - первое выполнение, а проверка вне первого foreach - второе выполнение.

Вы должны позвонить ToList, если вы хотите работать с такими же экземплярами в таком сценарии.

1 голос
/ 24 мая 2011

Когда вы проверяете объекты во второй раз, вы переоцениваете перечисляемое значение objects?Потому что это заставило бы его снова вызывать фасад.Как то так:

IEnumerable<MyObject> objects = 
    (from id in ids 
     select facade.GetObjectById(id)).ToArray();
0 голосов
/ 24 мая 2011

Я предполагаю, что вы используете SQL-сервер, откуда поступают данные?

Запрос будет оставаться в пространстве LINQ to SQL, пока, как предлагается в обоих предыдущих ответах, вы не вызовете ToList () или ToArray () или подобное. Только тогда он фактически становится LINQ to Object, и данные создаются и сохраняются в памяти вашей программы.

Таким образом, после внесения изменений в список вы можете выполнить тот же запрос еще раз и получить другой список, в котором нет ваших изменений.

Может быть, лучше объяснить следующее:

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

Это выдаст ошибку, потому что нет перевода из строки. IsNullOrEmpty в SQL.

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

Это не выдаст ошибку, потому что после ToList () вы находитесь в объектном пространстве.

...