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

时间:2011-11-14 16:57:57

标签: c# xml-serialization dataset

我正在尝试使用代码将数据集导出为XML。

这就是我目前使用的:

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

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

我收到以下错误:“无法继续序列化DataTable'TABLE'。它包含一个DataRow,它在同一个外键上有多个父行。

Cna有人给我一些关于我做错的指示吗?为什么我收到此错误消息?

提前致谢。

2 个答案:

答案 0 :(得分:2)

我知道它有点晚了,但我找到了解决方法。

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

数据集以两种模式运行,但您无法从外部说明这一点。

  1. (a)我是严格/手动创建的数据集,不喜欢嵌套关系
  2. (b)我是一个序列化对象的容器,一切顺利。
  3. 您创建的数据集目前是' a'我们希望将其设为' b'。 它运行的模式是在DatSet被加载时决定的。 (xml)和/或其他一些注意事项。

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

    诀窍是欺骗数据集,使其认为自己构建所有关系。我发现这样做的唯一方法是通过使用序列化来实际创建数据集。

    (我们在我们系统的一部分中使用此解决方案,我们使用面向DataSet的第三方产品创建输出。)

    在meta中,您想要做的是:

    1. 在代码中创建数据集,包括关系。试试你 可以模仿MS命名约定(虽然不确定是否需要)
    2. 序列化您的数据集(最好不要有任何行)
    3. 使序列化数据集看起来像MS序列化它。 (I' 11 在下面进行扩展)
    4. 将修改后的数据集读入新实例。
    5. 现在您可以导入行,MS不会检查关系, 事情应该有效。
    6. 一些实验告诉我,在这种情况下,少即是多。 如果DataSet读取架构,并找到NO关系或Key-Columns,它将以模式&b;#b;否则它将在模式' a'中工作。 我们仍然可以获得一个' b'具有SOME关系或Key-Columns的模式数据集,但这与我们的问题无关。

      所以,我们开始,这段代码假设你有一个扩展方法'序列化'知道如何处理数据集。

      假设sourceDataSet是仅包含模式的DataSet。 目标将是实际可用的数据集:

      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);
      }
      

      注意,正如我在开始时所说的那样,我在加载数据集时必须解决这个问题,虽然您要保存数据集,但解决方法也是一样的。

答案 1 :(得分:1)

这两个外键导致了这个问题。键的另一端被认为是父母,所以你有两个。在编写XML时,元素只能有一个父元素(除非元素出现两次,每个父元素下面一次)。可能的解决方案包括删除其中一个外键(我很欣赏可能会以其他方式破坏您的应用),或者,根据dataSet的初始化方式,尝试将EnforceConstraints设置为false