我知道这有点晚了,但我找到了解决方法。
我在尝试将架构读入具有关系的数据集时遇到了同样的问题。在这种情况下,您将得到的错误是:
'同一个表'{0}'不能是两个嵌套关系中的子表'
我将分享我所学到的
数据集以两种模式运行,但您无法从外部分辨出来。
- (a) 我是严格/手动创建的数据集,不喜欢嵌套关系
- (b) 我是一个序列化对象的容器,一切正常。
您创建的数据集当前为“a”,我们希望将其设为“b”。
在“加载”数据集 (xml) 或其他一些考虑因素时决定它以哪种模式运行。
我花了很多时间阅读 DataSet 的代码以找出一种欺骗它的方法,我发现 MS 可以通过在数据集上添加一个属性和一些额外的检查来解决这个问题。查看 DataRelation 的源代码:http://referencesource.microsoft.com/#System.Data/System/Data/DataRelation.cs,d2d504fafd36cd26,references,我们需要欺骗的唯一方法是 'ValidateMultipleNestedRelations' 方法。)
诀窍是欺骗数据集,使其认为它自己建立了所有关系。我发现这样做的唯一方法是通过使用序列化实际让数据集创建它们。
(我们在系统的一部分中使用此解决方案,我们正在使用面向 DataSet 的第 3 方产品创建输出。)
在meta中,你要做的是:
- 在代码中创建数据集,包括关系。如果你试试
可以模仿 MS 命名约定(虽然不确定是否需要)
- 序列化您的数据集(最好不要在其中包含任何行)
- 使序列化数据集看起来像 MS 序列化它。 (生病
在下面展开)
- 将修改后的数据集读入新实例。
- 现在您可以导入您的行,MS 不检查关系,
事情应该会奏效。
一些实验告诉我,在这种情况下,少即是多。
如果一个 DataSet 读取一个模式,并且发现没有关系或键列,它将在模式“b”下运行,否则它将在模式“a”下运行。
有可能我们仍然可以获得具有某些关系或键列的“b”模式数据集,但这与我们的问题无关。
所以,我们开始吧,这段代码假设您有一个知道如何处理数据集的扩展方法“Serialize”。
假设 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);
}
注意,正如我在开始时所说的,当我们加载数据集时,我必须解决这个问题,虽然您正在保存数据集,但解决方法将是相同的。