使用WriteXML方法时的序列化问题

本文关键字:序列化 问题 WriteXML 方法 使用 | 更新日期: 2023-09-27 18:14:48

我想用代码做的是将数据集导出为XML。

这是我目前使用的:

dataSet.WriteXml(fileDialog.FileName, XmlWriteMode.WriteSchema);

My dataSet是一个正确形成的类型化数据集(我的意思是,所有表都有PK关系,并且数据集中所有现有表之间设置了FK关系)。有些关系是嵌套关系。表" table "有两个FK,同时是其他8个表的父表。

我得到以下错误:"不能继续序列化数据表'TABLE'。它包含一个DataRow,在同一个外键上有多个父行。

谁能给我一些指点我做错了什么?为什么我得到这个错误信息?

使用WriteXML方法时的序列化问题

我知道有点晚了,但我已经找到了一个解决办法。

在尝试将模式读取到具有关系的数据集时,我遇到了同样的问题。在这种情况下,你会得到的错误是:'同一个表'{0}'不能是两个嵌套关系中的子表'我将分享我所学到的

数据集以两种模式运行,尽管你不能从外部看出这一点。

  1. (a)我是一个严格的/手动创建的数据集,不喜欢嵌套关系
  2. (b)我是一个序列化对象的容器,一切顺利。

您创建的数据集当前是'a',我们想让它成为'b'。当DatSet被"加载"(xml)或其他一些考虑因素时,它以哪种模式运行。

我花了狂热的时间阅读数据集的代码来找出欺骗它的方法,我发现MS可以通过在数据集上添加属性和一些额外的检查来解决问题。检查datarerelationshttp://referencesource.microsoft.com/#System.Data/System/Data/DataRelation.cs,d2d504fafd36cd26,references的源代码,我们需要欺骗的唯一方法是'ValidateMultipleNestedRelations'方法。

诀窍是欺骗数据集,让它认为它自己建立了所有的关系。我发现这样做的唯一方法是通过使用序列化让数据集创建它们。

(我们在系统中使用此解决方案,我们使用面向数据集的第三方产品创建输出)

在meta中,你要做的是:

    在代码中创建数据集,包括关系。你可以试试可以模仿MS命名约定(虽然不确定是否需要)
  1. 序列化你的数据集(最好没有任何行)
  2. 使序列化的数据集看起来像MS序列化的数据集。(我将在下面展开)
  3. 将修改后的数据集读入新实例。
  4. 现在您可以导入您的行,MS不检查关系,
一些实验告诉我,在这种情况下,少即是多。如果一个数据集读取一个模式,并且没有发现任何关系或键列,它将在模式'b'中运行,否则它将在模式'a'中工作。有可能我们仍然可以获得具有一些关系或键列的'b'模式数据集,但这与我们的问题无关。

那么,我们开始吧,这段代码假设你有一个扩展方法'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