«Это ограничение нельзя включить, поскольку не все значения имеют соответствующие родительские значения». - PullRequest
0 голосов
/ 28 мая 2020

Я хочу создать вложенный XML DataTable, но по какой-то причине он продолжает выдавать мне ошибку: This constraint cannot be enabled as not all values have corresponding parent values. Это результат XML, на который я надеюсь:

<Annotation>
  <Information>
    <folder>Kangaroo</folder>
    <filename>00001.JPG</filename>
  </Information>
  <size>
    <width>1024</width>
    <height>1024</height>
    <depth>3</depth>
  </size>
  <object>
    <bndbox>
      <ID>1</ID>
      <xmin>143</xmin>
      <ymin>163</ymin>
      <xmax>332</xmax>
      <ymax>335</ymax>
    </bndbox>
  </object>
</Annotation>

Я попытался установить идентификатор в bndbox в качестве первичного ключа, создав ограничение внешнего ключа и установив параметр createConstraints в методе Relations.Add значение false. Последний из трех создал файл XML, но не создал контейнер object, который выглядит следующим образом:

<Annotation>
  <Information>
    <folder>Kangaroo</folder>
    <filename>00001.JPG</filename>
  </Information>
  <size>
    <width>1024</width>
    <height>1024</height>
    <depth>3</depth>
  </size>
  <bndbox>
    <ID>1</ID>
    <xmin>143</xmin>
    <ymin>163</ymin>
    <xmax>332</xmax>
    <ymax>335</ymax>
  </bndbox>
</Annotation>

Мой текущий код:

//create object table
DataTable tableObj2 = new DataTable();
tableObj2.TableName = "object";

//add column id
DataColumn objIdColumn = new DataColumn();
objIdColumn.DataType = System.Type.GetType("System.Int32");
objIdColumn.ColumnName = "ID";
tableObj2.Columns.Add(objIdColumn);
tableObj2.PrimaryKey = new DataColumn[1] { objIdColumn };
DataRow row = tableObj2.NewRow();
row["ID"] = 1;

//create binding box table
DataTable tableBb2 = new DataTable();
tableBb2.TableName = "bndbox";
DataRow dataRow4 = tableBb2.NewRow();

//add column id and coordinates
tableBb2.Columns.Add("ID", typeof(int));
tableBb2.Columns.Add("xmin", typeof(int));
tableBb2.Columns.Add("ymin", typeof(int));
tableBb2.Columns.Add("xmax", typeof(int));
tableBb2.Columns.Add("ymax", typeof(int));

//insert values
dataRow4["ID"] = 1;
dataRow4["xmin"] = dataGridView1.Rows[0].Cells[1].Value;
dataRow4["ymin"] = dataGridView1.Rows[0].Cells[2].Value;
dataRow4["xmax"] = dataGridView1.Rows[1].Cells[1].Value;
dataRow4["ymax"] = dataGridView1.Rows[1].Cells[2].Value;
tableBb2.Rows.Add(dataRow4);

//add tables to Annotation dataset
ds.Tables.Add(tableBb2);
ds.Tables.Add(tableObj2);

//create data relation
DataRelation relation = ds.Relations.Add("relation", ds.Tables["object"].Columns["ID"], ds.Tables["bndbox"].Columns["ID"]);
relation.Nested = true;

Приветствуются любые указания или помощь!

1 Ответ

1 голос
/ 28 мая 2020

Это ограничение нельзя включить, поскольку не все значения имеют соответствующие родительские значения.

Здесь вы создали новую строку для родительской таблицы:

DataRow row = tableObj2.NewRow();

Но вы, похоже, не добавили ее в родительскую таблицу. Я ожидал увидеть где-нибудь подобный код, прежде чем вы попытаетесь добавить строки в дочернюю таблицу, которая ссылается на эту новую строку:

tableObj2.Rows.Add(row);

Поскольку вы никогда не добавляли эту строку, ваш код до сих пор работает успешно вы сообщаете DataSet, что эти таблицы связаны между собой, и в этот момент он сообщает, что «одна или несколько строк в вашей дочерней таблице не имеют соответствующей родительской строки в родительской таблице»

Помните; вызов NewRow дает новую отдельную строку. Его нужно добавить в таблицу, чтобы он функционировал как часть отношений.


Согласно другим новостям, ваша жизнь станет намного лучше, если вы щелкните правой кнопкой мыши свой проект, добавите новый элемент, категорию данных, введите DataSet .. откройте DataSet, щелкните правой кнопкой мыши область конструктора и выберите Добавить .. Datatable. Укажите свои столбцы, щелкнув его правой кнопкой мыши и выбрав add..column. Укажите свое отношение, щелкнув серую часть строки рядом с именем столбца в родительском идентификаторе, чтобы вся строка стала синей, а затем перетащите синюю строку на дочерний идентификатор в другой таблице данных и отпустите ее. Это делает типизированный DataSet. С ними намного приятнее работать в intellisense, потому что они ввели свойства для столбцов et c, поэтому ни один из этих row["ID"] = 1 или var x = (int)row["ID"] - строка будет иметь свойство ID, которое является целым числом, поэтому это row.ID = 1 или var x = row.ID - строго типизированный, а не строго типизированный:)

Если вы все же создаете строго типизированный DataSet, помните это простое правило: если вы обращаетесь к коллекциям .Rows или .Columns (или помещаете имя столбца в строка) вы, вероятно, делаете это неправильно. Эти коллекции возвращают базовые объекты DataRow / DataColumn, которые возвращают вас в строго типизированный мир

//no
dt.Rows[0]

//yes
dt[0]

//no
dt.Columns["Colname"]

//yes
dt.ColnameColumn

//no
dt[0].IsNull("Colname")

//yes
dt[0].IsColnameNull()
...