使用WriteXML方法时的序列化问题
本文关键字:序列化 问题 WriteXML 方法 使用 | 更新日期: 2023-09-27 18:14:48
我想用代码做的是将数据集导出为XML。
这是我目前使用的:
dataSet.WriteXml(fileDialog.FileName, XmlWriteMode.WriteSchema);
My dataSet是一个正确形成的类型化数据集(我的意思是,所有表都有PK关系,并且数据集中所有现有表之间设置了FK关系)。有些关系是嵌套关系。表" table "有两个FK,同时是其他8个表的父表。
我得到以下错误:"不能继续序列化数据表'TABLE'。它包含一个DataRow,在同一个外键上有多个父行。 谁能给我一些指点我做错了什么?为什么我得到这个错误信息?
我知道有点晚了,但我已经找到了一个解决办法。
在尝试将模式读取到具有关系的数据集时,我遇到了同样的问题。在这种情况下,你会得到的错误是:'同一个表'{0}'不能是两个嵌套关系中的子表'我将分享我所学到的
数据集以两种模式运行,尽管你不能从外部看出这一点。
- (a)我是一个严格的/手动创建的数据集,不喜欢嵌套关系
- (b)我是一个序列化对象的容器,一切顺利。
您创建的数据集当前是'a',我们想让它成为'b'。当DatSet被"加载"(xml)或其他一些考虑因素时,它以哪种模式运行。
我花了狂热的时间阅读数据集的代码来找出欺骗它的方法,我发现MS可以通过在数据集上添加属性和一些额外的检查来解决问题。检查datarerelationshttp://referencesource.microsoft.com/#System.Data/System/Data/DataRelation.cs,d2d504fafd36cd26,references的源代码,我们需要欺骗的唯一方法是'ValidateMultipleNestedRelations'方法。
诀窍是欺骗数据集,让它认为它自己建立了所有的关系。我发现这样做的唯一方法是通过使用序列化让数据集创建它们。
(我们在系统中使用此解决方案,我们使用面向数据集的第三方产品创建输出)
在meta中,你要做的是:
- 在代码中创建数据集,包括关系。你可以试试可以模仿MS命名约定(虽然不确定是否需要)
- 序列化你的数据集(最好没有任何行)
- 使序列化的数据集看起来像MS序列化的数据集。(我将在下面展开) 将修改后的数据集读入新实例。
- 现在您可以导入您的行,MS不检查关系,
那么,我们开始吧,这段代码假设你有一个扩展方法'Serialize',它知道如何处理数据集。
假设sourceDataSet是只有模式的数据集。目标将是实际可用的数据集:
var sourceDataSet = new DataSet();
var source = sourceDataSet.Serialize();
// todo: create the structure of your dataset.
var endTagKeyColumn = " msdata:AutoIncrement='"true'" type='"xs:int'" msdata:AllowDBNull='"false'" use='"prohibited'" /";
var endTagKeyColumnLength = endTagKeyColumn.Length - 1;
var startTagConstraint = "<xs:unique ";
var endTagConstraint = "</xs:unique>";
var endTagConstraintLength = endTagConstraint.Length - 1;
var cleanedUp = new StringBuilder();
var subStringStart = 0;
var subStringEnd = source.IndexOf(endTagKeyColumn);
while (subStringEnd > 0)
{
// throw away unused key columns.
while (source[subStringEnd] != '<') subStringEnd--;
if (subStringEnd - subStringStart > 5)
{
cleanedUp.Append(source.Substring(subStringStart, subStringEnd - subStringStart));
}
subStringStart = source.IndexOf('>', subStringEnd + endTagKeyColumnLength) + 1;
subStringEnd = source.IndexOf(endTagKeyColumn, subStringStart);
}
subStringEnd = source.IndexOf(startTagConstraint, subStringStart);
while (subStringEnd > 0)
{
// throw away relationships.
if (subStringEnd - subStringStart > 5)
{
cleanedUp.Append(source.Substring(subStringStart, subStringEnd - subStringStart));
}
subStringStart = source.IndexOf(endTagConstraint, subStringEnd) + endTagConstraintLength;
subStringEnd = source.IndexOf(startTagConstraint, subStringStart);
}
cleanedUp.Append(source.Substring(subStringStart + 1));
target = new DataSet();
using (var reader = new StringReader(cleanedUp.ToString()))
{
target.EnforceConstraints = false;
target.ReadXml(reader, XmlReadMode.Auto);
}
注意,正如我在开始时所说的,我必须在加载数据集时解决这个问题,虽然您正在保存数据集,但解决方法将是相同的。
这两个外键导致了这个问题。钥匙的另一端被认为是父母,所以你有两个。在编写XML时,一个元素只能有一个父元素(除非该元素在每个父元素下出现两次)。可能的解决方案包括删除一个外键(我欣赏可能会以其他方式破坏您的应用程序),或者,根据您的dataSet
初始化方式,尝试将EnforceConstraints
设置为false
。