2011-09-05 1 views
5

Я думаю, что у меня сегодня своя голова: У меня есть IEnumerable типа POCO, содержащего около 80 000 строк и таблицу db (L2E/EF4), содержащую подмножество строк, где была «ошибка/разность "(около 5000 строк, но часто повторяются, чтобы дать около 150 различных записей * сильного текста *)Обновить объект в IEnumerable <> не обновлять?

Следующего код получает отчетливое VSACode в„ошибочном“, а затем пытается обновить полный набор результатов, обновление только строки, которые соответствуют ... но это не работает!

Какая глупость я сделал ?!

var vsaCodes = (from g in db.GLDIFFLs 
    select g.VSACode) 
    .Distinct(); 

foreach (var code in vsaCodes) 
{ 
    var hasDifference = results.Where(r => r.VSACode == code); 
    foreach (var diff in hasDifference) 
    diff.Difference = true; 
} 

var i = results.Count(r => r.Difference == true); 

После этого кода, я = 0

Я также попытался:

foreach (var code in vsaCodes) 
      { 
       results.Where(r => r.VSACode == code).Select(r => { r.Difference = true; return r; }).ToList(); 
      } 

Как я могу обновить "результаты", чтобы установить только свойство соответствия разница?

ответ

10

Предполагая, что results - это всего лишь запрос (вы его не показали), он будет оцениваться каждый раз, когда вы перебираете его. Если этот запрос каждый раз создает новые объекты, вы, , не будете см. Обновления. Если он вернет ссылки на те же объекты, вы бы это сделали.

При изменении results будет материализовано результат запроса - например. добавив ToList() до конца - тогда итерация по resultsне будет выдать новый запрос, и вы увидите свои изменения.

+0

Мое понимание (явно не совсем правильное) заключалось в том, чтобы избежать использования ToList(), если вы действительно не нуждаетесь в этом ... Я думаю, что это ситуация «действительно нужна»? Быстрый Q? лучше ли называть ToList() на ранней стадии моей цепочкой высказываний/запросов для материализации списка? Если я этого не сделаю, будет ли он запрашивать DB каждый раз, когда он будет использоваться? – BlueChippy

+0

@BlueChippy: Обычно вы должны использовать ToList как можно дольше, так что большая часть запроса (в частности, части, которые фильтруют вывод) выполняется в базе данных. –

+0

Спасибо, Jon, думаю, я оставил этот ToList() немного TooLate();) – BlueChippy

2

У меня была такая же ошибка некоторое время назад. Проблема в том, что запросы linq часто откладываются и не выполняются, когда кажется, что вы их вызываете.

Цитата из «Pro LINQ Language Integrated Query в C# 2010»:

«Обратите внимание, что даже если мы назвали запрос только один раз, результаты перечисление различны для каждого из перечислений Это еще одно доказательство того, что запрос отложен. Если бы это не так, то результаты обоих перечислений были бы одинаковыми. Это может быть выигрыш или ущерб . Если вы не хотите, чтобы это произошло, используйте один из операторы преобразования, которые не возвращают IEnumerable, так что запрос не откладывается, например ToArray, ToList, ToDictionary или ToLookup, чтобы создать другую структуру данных с кэшированными результатами , которые не будут меняться при изменении источника данных. "

Здесь у вас есть хорошее объяснение с примерами этого:

http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx

С уважением

0

PARSING слова довольно тесно на @ jonskeet отвечают ...

Если ваш запрос является просто фильтром, а исходные исходные объекты обновляются, запрос будет переоценен и может исключать эти объекты на основе условия фильтра, и в этом случае ваши результаты запроса будут изменены при последующих перечислениях, но базовые объекты будут все еще обновлены.

Ключ - это отсутствие проекции на новый тип при обновлении и сохранении измененных объектов.

ToList() является обычным решением этой проблемы, и это решит проблему, если есть проекция на новый тип, но все становится мутным, если ваши фильтры запросов, но не проецируются. Обновления запроса по-прежнему влияют на исходные исходные объекты, если все равно referencing того же объекта.

Опять разбор слов, но эти краевые кейсы могут вас трогать.

public class Widget 
{ 
    public string Name { get; set; } 
} 

var widgets1 = new[] 
{ 
    new Widget { Name = "Red", }, 
    new Widget { Name = "Green", }, 
    new Widget { Name = "Blue", }, 
    new Widget { Name = "Black", }, 
}; 

// adding ToList() will result in 'static' query result but 
// updates to the objects will still affect the source objects 
var query1 = widgets1 
    .Where(i => i.Name.StartsWith("B")) 
    //.ToList() 
    ; 

foreach (var widget in query1) 
{ 
    widget.Name = "Yellow"; 
} 

// produces no output unless you uncomment out the ToList() above 
// query1 is reevaluated and filters out "yellow" which does not start with "B" 
foreach (var name in query1) 
    Console.WriteLine(name.Name); 

// produces Red, Green, Yellow, Yellow 
// the underlying widgets were updated 
foreach (var name in widgets1) 
    Console.WriteLine(name.Name); 

 Смежные вопросы

  • Нет связанных вопросов^_^