Сериализация объекта Entity Framework с дочерними объектами в файл XML - PullRequest
5 голосов
/ 04 июня 2011

Я запрашиваю данные с помощью родительских / дочерних наборов результатов, используя Entity Framework, и хочу экспортировать эти данные в документ XML.

var agreement = storeops.Agreements.SingleOrDefault(a => a.AgreementNumber == AgreementTextBox.Text);
XmlSerializer serializer = new XmlSerializer(agreement.GetType());
XmlWriter writer = XmlWriter.Create("Agreement.xml");
serializer.Serialize(writer, agreement);

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

Я также пытался использовать сгенерированный POCO-код, и дочерние коллекции пытаются сериализоваться, за исключением того, что они представляют собой ICollections, которые не могут быть сериализованы.

НевозможноСериализуйте член DataSnapshots.Agreement.AgreementItems типа System.Collections.Generic.ICollection`1 [[DataSnapshots.AgreementItem, DataSnapshots, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = null]], поскольку он является интерфейсом.

Ответы [ 2 ]

10 голосов
/ 04 июня 2011

XML-сериализация ведет себя иначе, чем двоичная сериализация и сериализация контракта данных при работе с объектами Entity Framework. Последний будет сериализовать любые связанные объекты, которые были загружены в граф объектов, но XML-сериализация не делает, поэтому вам нужно будет использовать DataContractSerializer:

var agreement = storeops.Agreements.SingleOrDefault(a => a.AgreementNumber == AgreementTextBox.Text);
// make sure any relations are loaded

using (XmlWriter writer = XmlWriter.Create("Agreement.xml"))
{
    DataContractSerializer serializer = new DataContractSerializer(agreement.GetType());
    serializer.WriteObject(writer, agreement);
}

Кроме того, Entity Framework по умолчанию использует ленивую загрузку для 1: многих отношений, и если ссылочные объекты еще не были загружены при сериализации, то все, что вы получите, - это ключи, которые к ним относятся. Вы должны явно загрузить связанные сущности, вызвав agreement.Children.Load() или используя .Include("Children") в своем запросе (где "Children" - имя коллекции связанных сущностей).

0 голосов
/ 05 июня 2011

Я наконец-то нашел решение этой проблемы, но для этого нужно отредактировать сгенерированные классы: (

Создать сгенерированные классы сущностей POCO, установить для Lazy Loading значение true, которое получит родительский элемент и всех потомков с одним выбором (без использования Include или Load).

В родительском классе измените тип дочернего метода доступа с ICollection на FixupCollection.

публичная виртуальная FixupCollection AgreementItemLogs

Затем в XmlSerializer вынеобходимо указать родительский тип и дочерние типы из прокси-классов.

var agreement = storeops.Agreements.Include("AgreementItems").SingleOrDefault(a => a.AgreementNumber == AgreementTextBox.Text);                                             
                var typeList = new List<Type>();

                if(agreement.AgreementItems.Count > 0)
                    typeList.Add(agreement.AgreementItems.FirstOrDefault().GetType());
                if (agreement.AgreementItemLogs.Count > 0)
                    typeList.Add(agreement.AgreementItemLogs.FirstOrDefault().GetType());
                if (agreement.AgreementPricings.Count > 0)
                    typeList.Add(agreement.AgreementPricings.FirstOrDefault().GetType());
                if (agreement.AgreementSnapshots.Count > 0)
                    typeList.Add(agreement.AgreementSnapshots.FirstOrDefault().GetType());
                if (agreement.AgreementTransactions.Count > 0)
                    typeList.Add(agreement.AgreementTransactions.FirstOrDefault().GetType());
                if (agreement.AgreementTransactionLogs.Count > 0)
                    typeList.Add(agreement.AgreementTransactionLogs.FirstOrDefault().GetType());

                XmlSerializer serializer = new XmlSerializer(agreement.GetType(), typeList.ToArray());
                XmlWriter writer = XmlWriter.Create("Agreement.xml");
                serializer.Serialize(writer, agreement);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...