Устранение циклов в графе объектов EF 4 STE
Я вернулся к "доске для рисования" в посте, который я написал ранее относительно StackruException, при попытке сериализации графа объектов EF STE... После неудачной попытки отрегулировать размер стека в IIS7, как описано здесь, я решил пойти вниз по пути изучения коренной причины...
Я считаю, что это связано с тем, как была разработана модель EF.
Упрощенно, у меня есть родительский объект и дочерний объект. Дочерний объект имеет два свойства навигации обратно к Parent, например Child.Parent и Child.ParentUsed. Естественно, у родителя есть две дочерние коллекции.
Посмотрев ближе на данные, которые вызывают исключение Stackru, я заметил, что в этом графе объектов есть несколько циклов. Я не могу доказать это, но я вполне уверен, что циклы вызывают это исключение Stackru.
Если я удалю данные этой таблицы в базе данных, проблема исчезнет, но я не смогу удалить записи на компьютере клиента. Плохой дизайн или нет, я должен как-то обойти это на уровне EF.
Какие у меня есть варианты переделать это? Если бы у моего объекта Child не было свойств навигации обратно к родителю, но вместо этого было два целых Fks, я хотел бы знать, будут ли циклы, которые вызывали бы удушение сериализации? Есть ли способ изменить свойства навигации на Fks на одном объекте?
Спасибо!
Обновить:
Удаление обоих дочерних свойств навигации обратно к родителю решает эту проблему. Я не думаю, что это обязательно проблема циклов, но, возможно, стек исчерпан, пытаясь проверить ссылки и определить циклы.
Я не обязательно хочу удалить свойства nav. Они полезны на клиенте. Есть ли лучший способ исправить это? Пользовательская сериализация?
1 ответ
У меня была похожая проблема, когда я тестировал производительность EF с WCF. Я получал Stackru, когда набор результатов запроса превышал 3000 результатов.
Если вы удалите только одно из навигационных свойств, Stackru исчезнет. Я попытаюсь объяснить, где происходит цикл, но вы все также можете попытаться сериализовать свой график в файл с помощью DataContractSeriazer, и вы поймете, что не так, как только вы увидите сгенерированный XML.
Каждый объект сериализуется только один раз, однако сериализация - это сначала глубина. Используя свой сценарий в качестве примера:
1 - сериализация parent1
2 - сериализовать первый элемент ChildList1
3 - теперь мы сериализуем объект Child1, который имеет отношение к parent1 (уже сериализован, поэтому используется ссылка). Так что сериализуйте ParentUsed (другой объект parent2 с большим количеством связей с другими потомками) - перейдите к шагу 1 для parent2
Если список загруженных родителей и сложность отношений (между записями) достаточно велики, сериализатор попытается сериализовать весь граф как "потомки" (рекурсивно) первого элемента. Удаление одного из навигационных свойств обратно к родителю устранит цикл, поскольку оставшееся навигационное свойство всегда будет ссылаться на родительский объект, который уже был сериализован.
Если вы используете навигационные свойства только для привязки к пользовательскому интерфейсу, вы можете использовать более одного BindingSource (я использовал для WinForms) и FK для создания отношений и достижения того же результата, что и для навигационных свойств (хотя при этом требуется больше работы).
Надеюсь это поможет,
Нуно Перейра