6

我正在使用实体框架查询带有父/子结果集的数据,并且我想将此数据导出到 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。

无法序列化 System.Collections.Generic.ICollection`1[[DataSnapshots.AgreementItem, DataSnapshots, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] 类型的成员 DataSnapshots.Agreement.AgreementItems,因为它是一个接口。

4

2 回答 2

10

在使用 Entity Framework 实体时,XML 序列化的行为不同于二进制序列化和数据协定序列化。后者将序列化任何已加载到对象图中的相关对象,但 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:Many 关系使用延迟加载,如果在序列化时引用的对象尚未加载,那么您将得到的只是引用它们的键。您必须通过调用agreement.Children.Load().Include("Children")在查询中使用来显式加载相关实体("Children"相关实体集合的名称在哪里)。

于 2011-06-04T03:17:51.850 回答
0

我终于想出了一个解决方案,但它确实需要编辑生成的类:(

创建 POCO 生成的实体类,将 Lazy Loading 设置为 true,这将通过一次选择(无需使用 Include 或 Load)来获取父级和所有子级。

在父类上,将子访问器类型从 ICollection 修改为 FixupCollection。

公共虚拟 FixupCollection 协议项日志

然后在 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);
于 2011-06-05T16:28:34.450 回答