Изменение значения работает с быстрой загрузкой, но не с отложенной загрузкой в ​​linq и ef - PullRequest
3 голосов
/ 21 мая 2011

это не вопрос проблема , а вопрос почему это происходит вопрос.

var chapters = story.Chapters.Select(
                    ch => new ChapterDisplayViewModel { 
                                   Id = ch.Id,
                                   Number = ch.Number});

сначала я хочу получить некоторые данные.story - это тип сущности типа Story, который имеет отношение «один ко многим» с Chapter я хочу изменить некоторые данные в коллекции глав, которые я получил, поэтому я пишу некоторые условия, если это так, измените значение

if(chapters.Any(c => c.Number == chapterNum))
   chapters.Where(c => c.Number == chapterNum).Single().IsSelected = true;

и затем я отправляю данные в представление, но проблема заключается в следующем:

ничего не изменилось из-за отложенной загрузки, внесенные мной изменения не сработали даже после отправки данных в представление, Почему?я сделал оценку присвоения, и не должна ли передача данных в представление вызвать его?

решение, конечно, было использовать ToList для немедленного выполнения запроса

var chapters = story.Chapters.Select(
                    ch => new ChapterDisplayViewModel { 
                                   Id = ch.Id,
                                   Number = ch.Number}).ToList();

я простохочу объяснение поведению

1 Ответ

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

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

var chapters = story.Chapters.Select(
               ch => new ChapterDisplayViewModel { 
                               Id = ch.Id,
                               Number = ch.Number});

... выполняет запрос в базе данных, который запрашивает все Chapter объекты (проекция на ChapterDisplayViewModel не происходит в базе данных).И это единственный запрос к базе данных.Следующее ...

if (chapters.Any(c => c.Number == chapterNum))
    chapters.Where(c => c.Number == chapterNum).Single().IsSelected = true;

... выполняется в памяти уже загруженной коллекции Chapters.Проекция происходит в этой точке.

Но это означает, что оператор Single материализует объект ChapterDisplayViewModel, это означает: где-то внутри new ChapterDisplayViewModel происходит.Простая проверка:

var viewModel1 = chapters.Where(c => c.Number == chapterNum).Single();
var viewModel2 = chapters.Where(c => c.Number == chapterNum).Single();

bool sameObjects = object.ReferenceEquals(viewModel1, viewModel2);

sameObjects - это false, что означает, что Single не просто возвращает ссылки на объекты ViewModel, которые уже находятся в памяти, но создает их новые экземпляры.

Когда вы применяете ToList в первом запросе, ViewModels сразу материализуются в коллекцию ViewModels в памяти, и Single просто возвращает ссылку на соответствующий, но уже существующий объект.sameObjects будет true.

Итак, без ToList вы устанавливаете свойство IsSelected для только что материализованного объекта, на который вы больше не ссылаетесь, и поэтому сразу же исчезают в сборщике мусора.С ToList вы устанавливаете свойство для уникального объекта внутри коллекции в памяти.Когда вы используете эту коллекцию по вашему мнению, флаг все еще там.

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