Получить вложенный XML из DataSet с таблицей соединений - PullRequest
0 голосов
/ 06 марта 2020

У меня есть DataSet, состоящий из Authors и Books. Автор может иметь несколько книг. Книга может иметь несколько авторов. Итак, у меня есть таблица соединений AuthorBook. Я хотел бы сериализовать это в XML во вложенном виде.

Мой желаемый результат будет:

<MyDataSet>
  <Authors>
    <AuthorID>0</AuthorID>
    <Name>Anne Rice</Name>
    <Books>
      <Title>Interview with the vampire</Title>
    </Books>
    <Books>
      <Title>The vampire Armand</Title>
    </Books>
  </Authors>
  <Authors>
    <AuthorID>1</AuthorID>
    <Name>Stephen J Gould</Name>
    <Books>
      <Title>Wonderful life</Title>
    </Books>
  </Authors>
  ...
</MyDataSet>

Для иллюстрации у меня есть следующий код:

static void Main(string[] args)
{
    DataSet ds = CreateDataSet();
    PopulateDataSet(ds);
    ds.WriteXml(@"e:\temp\demo.xml");
    Console.WriteLine("Done");
    Console.Read();
}

static DataSet CreateDataSet()
{
    DataSet ds = new DataSet("MyDataSet");
    DataTable dt;
    DataColumn dc;
    // add authors table
    dt = new DataTable("Authors");
    dc = dt.Columns.Add("AuthorID", typeof(int));
    dc.AutoIncrement = true;
    dc.ReadOnly = true;
    dc = dt.Columns.Add("Name", typeof(string));
    dt.PrimaryKey = new DataColumn[] { dt.Columns["AuthorID"] };
    ds.Tables.Add(dt);
    // add books table
    dt = new DataTable("Books");
    dc = dt.Columns.Add("BookID", typeof(int));
    dc.AutoIncrement = true;
    dc.ReadOnly = true;
    dc = dt.Columns.Add("Title", typeof(string));
    dt.PrimaryKey = new DataColumn[] { dt.Columns["BookID"] };
    ds.Tables.Add(dt);
    // add link table
    dt = new DataTable("AuthorBook");
    dt.Columns.Add("AuthorID", typeof(int));
    dt.Columns.Add("BookID", typeof(int));
    dt.PrimaryKey = new DataColumn[] { dt.Columns["AuthorID"], dt.Columns["BookID"] };
    ds.Tables.Add(dt);
    // define relations: Authors has children in join table
    var r = ds.Relations.Add("AuthorsBooks",
        ds.Tables["Authors"].Columns["AuthorID"],
        ds.Tables["AuthorBook"].Columns["AuthorID"],
        true);
    r.Nested = true;
    // define relations: Books has children in join table
    r = ds.Relations.Add("BooksAuthors",
        ds.Tables["Books"].Columns["BookID"],
        ds.Tables["AuthorBook"].Columns["BookID"],
        true);
    r.Nested = true;
    return ds;
}

static void PopulateDataSet(DataSet ds)
{
    IList<string> authors = new List<string>() { "Anne Rice", "Stephen J Gould" };
    IList<string> books = new List<string>() { "Interview with the vampire", "The vampire Armand", "Wonderful life" };
    foreach (string s in authors)
    {
        DataRow row = ds.Tables["Authors"].NewRow();
        row["Name"] = s;
        ds.Tables["Authors"].Rows.Add(row);
    }
    foreach (string s in books)
    {
        DataRow row = ds.Tables["Books"].NewRow();
        row["Title"] = s;
        ds.Tables["Books"].Rows.Add(row);
    }
    // populate link table. Strictly arbitrary, just to have some data
    DataRow jtrow = ds.Tables["AuthorBook"].NewRow();
    jtrow["AuthorID"] = 0; // Anne Rice
    jtrow["BookID"] = 0; // Interview with the vampire
    ds.Tables["AuthorBook"].Rows.Add(jtrow);
    jtrow = ds.Tables["AuthorBook"].NewRow();
    jtrow["AuthorID"] = 0; // Anne Rice
    jtrow["BookID"] = 1; // The vampire Armand
    ds.Tables["AuthorBook"].Rows.Add(jtrow);
    jtrow = ds.Tables["AuthorBook"].NewRow();
    jtrow["AuthorID"] = 1; // Stephen J Gould
    jtrow["BookID"] = 2; // Wonderful life
    ds.Tables["AuthorBook"].Rows.Add(jtrow);
}

Этот код выдаст ошибку: Cannot proceed with serializing DataTable 'AuthorBook'. It contains a DataRow which has multiple parent rows on the same Foreign Key.

Я могу установить свойство Nested любого (или обоих) отношений на false, но это приведет к тому, что сама таблица соединения будет вложенный в мои выходные данные, или, если оба ложные, я просто получаю все данные «линейным» образом, из-за отсутствия лучшего слова.

Я довольно новичок в этом, и я чувствую, что мне не хватает часть головоломки. Пожалуйста, сообщите, спасибо.

...