问题描述
我正在尝试对代码执行的操作是将数据集导出到 XML.
What I'm trying to do with the code is to export a dataset to XML.
这是我目前正在使用的:
This is what I'm currently using:
dataSet.WriteXml(fileDialog.FileName, XmlWriteMode.WriteSchema);
我的数据集是一个正确形成的类型化数据集(我的意思是,所有表都有 PK,并且在数据集中所有现有表之间设置了 FK 关系).一些关系是嵌套关系.表TABLE"有两个 FK,同时是其他 8 个表的父级.
My dataSet is a typed dataset properly formed (by this I mean, all tables have PK, and FK relations are set between all existing tables in the dataSet). Some relationships are nested relationships. The table "TABLE" has two FK and at the same time is parent to other 8 tables.
我收到以下错误:无法继续序列化 DataTable 'TABLE'.它包含一个 DataRow,它在同一个外键上有多个父行."
有人给我一些关于我做错了什么的指点吗?以及为什么我会收到此错误消息?
Cna anyone give me some pointers on what I'm doing wrong? and why I'm getting this error message?
提前致谢.
推荐答案
我知道有点晚了,但我找到了解决方法.
I know it's a bit late, but I have found a workaround.
我在尝试将架构读入具有关系的数据集时遇到了同样的问题.在这种情况下,您将得到的错误是:'同一个表'{0}'不能是两个嵌套关系中的子表'我将分享我所学到的
I ran into the same problem while trying to read a schema into a dataset that has the relations. The error you will get in that case is:'The same table '{0}' cannot be the child table in two nested relations'I will share what I have learned
数据集以两种模式运行,但您无法从外部分辨出来.
The dataset operates in two modes, though you CAN NOT tell this from the outside.
- (a) 我是严格/手动创建的数据集,不喜欢嵌套关系
- (b) 我是一个序列化对象的容器,一切顺利.
您创建的数据集当前为a",我们希望将其设为b".在加载"数据集 (xml) 或其他一些考虑因素时决定它以哪种模式运行.
The dataset you have created is currently an 'a', we want to make it a 'b'.Which mode it operates in is decided when a DatSet is 'loaded' (xml) and or some other considerations.
我花了很多时间阅读 DataSet 的代码以找出一种欺骗它的方法,我发现 MS 可以通过在数据集上添加一个属性和一些额外的检查来解决这个问题.查看 DataRelation 的源代码:http://referencesource.microsoft.com/#System.Data/System/Data/DataRelation.cs,d2d504fafd36cd26,references,我们唯一需要欺骗的方法是ValidateMultipleNestedRelations"方法.)
I spend feverish hours reading the code of the DataSet to figure out a way to fool it, and I found that MS can fix the problem with just the addition of a property on the dataset and a few additional checks. Checkout the source code for the DataRelation: http://referencesource.microsoft.com/#System.Data/System/Data/DataRelation.cs,d2d504fafd36cd26,references and that the only method we need to fool is the 'ValidateMultipleNestedRelations' method.)
诀窍是欺骗数据集,使其认为它自己建立了所有关系.我发现这样做的唯一方法是通过使用序列化实际让数据集创建它们.
The trick is to fool the dataset into thinking it build all relationships itself. The only way I found to do that is to actually make the dataset create them, by using serialization.
(我们在系统的一部分中使用此解决方案,我们正在使用面向 DataSet 的第 3 方产品创建输出.)
(We are using this solution in the part of oursystem where we're creating output with a DataSet oriented 3rd party product.)
在meta中,你要做的是:
In meta, what you want to do is:
- 在代码中创建您的数据集,包括关系.如果你试试可以模仿 MS 命名约定(虽然不确定是否需要)
- 序列化您的数据集(最好不要在其中包含任何行)
- 使序列化数据集看起来像 MS 序列化它.(患病的在下面展开)
- 将修改后的数据集读入新实例.
- 现在您可以导入行,MS 不会检查关系,事情应该会奏效.
一些实验告诉我,在这种情况下,少即是多.如果一个 DataSet 读取一个模式,并且发现没有关系或键列,它将在模式b"下运行,否则它将在模式a"下运行.有可能我们仍然可以获得具有某些关系或键列的b"模式数据集,但这与我们的问题无关.
Some experimentation taught me that in this situation, less is more.If a DataSet reads a schema, and finds NO relationships or Key-Columns, it will operate in mode 'b' otherwise it will work in mode 'a'.It COULD be possible that we can still get a 'b' mode dataset with SOME relationships or Key-Columns, but this was not pertinent for our problem.
所以,我们开始吧,这段代码假设您有一个知道如何处理数据集的扩展方法Serialize".
So, here we go, this code assumes you have an extension method 'Serialize' that knows how to handle a dataset.
假设 sourceDataSet 是仅具有架构的 DataSet.目标将是实际可用的数据集:
Assume sourceDataSet is the DataSet with the schema only.Target will be the actually usable 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);
}
注意,正如我在开始时所说的,当我们加载数据集时,我必须解决这个问题,虽然您正在保存数据集,但解决方法是相同的.
Note, so as I said at the start, I had to fix this problem when we are loading the dataset, and though you are saving the dataset, the workaround will be the same.
这篇关于使用 WriteXML 方法时的序列化问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!