Я знаю, что уже немного поздно, но я нашел обходной путь.
Я столкнулся с той же проблемой при попытке прочитать схему в наборе данных, который имеет отношения. Ошибка, которую вы получите в этом случае:
'Одна и та же таблица' {0} 'не может быть дочерней таблицей в двух вложенных отношениях'
Я поделюсь тем, что я узнал
Набор данных работает в двух режимах, хотя вы НЕ МОЖЕТЕ сказать об этом извне.
- (a) Я - строгий / созданный вручную набор данных, не люблю вложенные отношения
- (б) Я контейнер для сериализованного объекта, все идет.
Созданный вами набор данных в настоящее время является 'a', мы хотим сделать его 'b'.
В каком режиме он работает, определяется, когда набор данных «загружен» (xml) и / или по другим причинам.
Я потратил лихорадочные часы, читая код DataSet, чтобы выяснить, как его обмануть, и обнаружил, что MS может решить проблему, просто добавив свойство в набор данных и несколько дополнительных проверок. Извлеките исходный код для DataRelation: http://referencesource.microsoft.com/#System.Data/System/Data/DataRelation.cs,d2d504fafd36cd26,references, и что единственный метод, который нам нужно обмануть, - это метод ValidateMultipleNestedRelations.)
Хитрость заключается в том, чтобы обмануть набор данных, заставив его думать, что он сам строит все отношения. Единственный способ, который я нашел, - это заставить набор данных создавать их, используя сериализацию.
(Мы используем это решение в той части нашей системы, где мы создаем выходные данные с помощью стороннего продукта, ориентированного на DataSet.)
В мета, что вы хотите сделать, это:
- Создайте свой набор данных в коде, включая отношения. Попробуй если ты
может имитировать соглашение об именах MS (хотя и не обязательно, если требуется)
- Сериализация набора данных (лучше, чтобы в нем не было строк)
- Сделать сериализованный набор данных похожим на сериализованный MS. (Больной
подробнее об этом ниже)
- Считать измененный набор данных в новый экземпляр.
- Теперь вы можете импортировать ваши строки, MS не проверяет отношения,
и все должно работать.
Некоторые эксперименты научили меня, что в этой ситуации меньше значит больше.
Если DataSet читает схему и находит НЕТ отношений или ключевых столбцов, он будет работать в режиме «b», в противном случае он будет работать в режиме «a».
МОЖЕТ быть возможным, что мы все еще можем получить набор данных режима 'b' с НЕКОТОРЫМИ отношениями или Key-Columns, но это не относилось к нашей проблеме.
Итак, этот код предполагает, что у вас есть метод расширения '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);
}
Обратите внимание, что, как я уже сказал в начале, мне пришлось решить эту проблему, когда мы загружаем набор данных, и хотя вы сохраняете набор данных, обходной путь будет таким же.