Poznáváme C# a Microsoft. NET 66. díl – XML a ADO. NET

Bližší pohled na to jakým způsobem je realizováno opěvované spojení hierarchického světa XML a relačního světa databází na úrovní ADO .NET je tématem tohoto dílu, který mimo jiné ukáže jak jsou v XML dokumentu představovány datové relace mezi tabulkami.
Poznáváme C# a Microsoft. NET 66. díl – XML a ADO. NET

Zápis a načtení schéma DataSetu

V minulém díle jsme se dozvěděli, že je možné pomocí metody WriteXml objektu DataSet zapsat obsah tohoto objektu do XML a také, že je možné pomocí metody ReadXml objekt DataSet daty z XML naplnit. Spolu s daty objektu DataSet je možné zapsat/načíst i XSD definující jeho schéma. Schématem objektu DataSet je myšleno schéma jednotlivých tabulek, které daný DataSet obsahuje. Schéma tabulky je tvořeno názvy a datovými typy jednotlivých sloupců, pro něž mohou být definována různá omezení. V případě, že naším požadavkem je zapsat pouze informace o daném schématu objektu DataSet do XSD můžeme využít instanční metody třídy DataSet, kterou je metoda WriteXmlSchema.

DataSet ds = new DataSet("EmployeesDataSet");
//vytvoreni tabulky o zamestnancich
DataTable employees = CreateEmployessTable();
ds.Tables.Add(employees);
//zapis schema do XSD
ds.WriteXmlSchema("EmployeesDataSet.xsd");

Do výsledného XSD jsou zapsány jednak názvy a datové typy sloupců, ale také je v XSD zaznamenáno jedno omezení, které omezuje hodnoty sloupce ID na unikátní hodnoty a to, že hodnoty tohoto sloupce mají být automaticky inkrementovány.

<?xml version="1.0" standalone="yes"?>
<xs:schema id="EmployeesDataSet" xmlns="" xmlns:xs="
http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <xs:element name="EmployeesDataSet" msdata:IsDataSet="true" msdata:Locale="cs-CZ">
    <xs:complexType>
      <xs:choice maxOccurs="unbounded">
        <xs:element name="Employees">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="ID" msdata:AutoIncrement="true" type="xs:int" />
              <xs:element name="FirstName" type="xs:string" minOccurs="0" />
              <xs:element name="SurName" type="xs:string" minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
    <xs:unique name="Constraint1">
      <xs:selector xpath=".//Employees" />
      <xs:field xpath="ID" />
    </xs:unique>
  </xs:element>
</xs:schema>

Pochopitelně je možný i postup opačným směrem, tedy že lze schéma objektu DataSet z XSD načíst a to pomocí metody ReadXmlSchema.

//vytvoreni noveho DataSetu
DataSet ds = new DataSet();
//bude 0
Console.WriteLine(ds.Tables.Count);
//nacteni schema z XSD
ds.ReadXmlSchema("EmployeesDataSet.xsd");
//bude jedna
Console.WriteLine(ds.Tables.Count);
//vypise Employees
Console.WriteLine(ds.Tables[0].TableName);

Po úspěšném vykonání této metody jsou do objektu DataSet vytvořeny tabulky (v našem příkladu pouze jedna) podle daného XSD včetně všech omezení a tudíž s nimi můžeme bez problémů pracovat, jako kdybychom je vytvořili „ručně“ pomocí našeho kódu nebo pomocí datového adaptéru.

Datové relace a XML

Jak jsme během našeho poměrně podrobného seznamování se s komponentou ADO .NET zjistili tak lze na úrovni objektu DataSet definovat datové relace mezi jednotlivými tabulkami, což jsme činili pomocí objektů typu DataRelation. Pojďme se podívat, jak se nám definice datové relace projeví do hierarchické (tedy XML) reprezentace DataSetu.

//vytvoreni DataSetu
DataSet ds = new DataSet("ProductsDataSet");
//vytvoreni tabukly o kategoriich
DataTable categories = CreateCategoriesTable();
//vytvoreni tabulky o produktech
DataTable products = CreateProductsTable();
//naplneni tabulek daty
CreateProducts(products);
CreateCategories(categories);
ds.Tables.Add(products);
ds.Tables.Add(categories);
//vytvoreni datove relace
DataRelation relation = new DataRelation("ProductCategory", categories.Columns["ID"], products.Columns["CategoryID"]);
ds.Relations.Add(relation);
//vypiseme XML reprezentaci DataSetu
ds.WriteXml(Console.Out);

Tento zdrojový kód by nám měl být známý. Jsou v něm vytvořeny dvě tabulky (Products, Categories) mezi kterými je vytvořena datová relace, protože každý objekt spadá do nějaké kategorie. Pokud si prohlédnete výstup tohoto kódu, který vypíše XML reprezentaci objektu DataSet s datovou relací zjistíte, že to do jaké kategorie daný objekt patří, není z této hierarchické reprezentace vůbec čitelné.

<ProductsDataSet>
  <Products>
    <ID>0</ID>
    <Name>Product0</Name>
    <Price>0</Price>
    <CategoryID>1</CategoryID>
  </Products>
  <Products>
    <ID>1</ID>
    <Name>Product1</Name>
    <Price>1000</Price>
    <CategoryID>1</CategoryID>
  </Products>
  <Products>
    <ID>2</ID>
    <Name>Product2</Name>
    <Price>2000</Price>
    <CategoryID>1</CategoryID>
  </Products>
  <Products>
    <ID>3</ID>
    <Name>Product3</Name>
    <Price>3000</Price>
    <CategoryID>2</CategoryID>
  </Products>
  <Products>
    <ID>4</ID>
    <Name>Product4</Name>
    <Price>4000</Price>
    <CategoryID>2</CategoryID>
  </Products>
  <Categories>
    <ID>1</ID>
    <Name>Category ONE</Name>
  </Categories>
  <Categories>
    <ID>2</ID>
    <Name>Category TWO</Name>
  </Categories>
</ProductsDataSet>

Takže význam datové relace není do světa XML promítnut. Jak toto napravit? Řešení je velmi jednoduché a nabízí se ve formě vnořených relací. K tomu nám stačí nastavit vlastnost Nested objektu Datové relace.

...
//vytvoreni datove relace
DataRelation relation = new DataRelation("ProductCategory", categories.Columns["ID"], products.Columns["CategoryID"]);
//oznacime relace jako vnorene
relation.Nested = true;
ds.Relations.Add(relation);
//vypiseme XML reprezentaci DataSetu
ds.WriteXml(Console.Out);

Po té co pomocí této vlastnosti nastavíme, že tato relace je vnořená, tak ono vnoření uvidíme právě na úrovní XML reprezentace objektu DataSet, který tuto relaci obsahuje. Po vypsání XML reprezentace DataSetu budou v každém elementu hlavní entity relace (v našem případě kategorie) vnořeny elementy představující entity vedlejší (produkt). Jak následek použití vnořených relací v XML vypadá, můžete vidět níže.

<ProductsDataSet>
  <Categories>
    <ID>1</ID>
    <Name>Category ONE</Name>
    <Products>
      <ID>0</ID>
      <Name>Product0</Name>
      <Price>0</Price>
      <CategoryID>1</CategoryID>
    </Products>
    <Products>
      <ID>1</ID>
      <Name>Product1</Name>
      <Price>1000</Price>
      <CategoryID>1</CategoryID>
    </Products>
    <Products>
      <ID>2</ID>
      <Name>Product2</Name>
      <Price>2000</Price>
      <CategoryID>1</CategoryID>
    </Products>
  </Categories>
  <Categories>
    <ID>2</ID>
    <Name>Category TWO</Name>
    <Products>
      <ID>3</ID>
      <Name>Product3</Name>
      <Price>3000</Price>
      <CategoryID>2</CategoryID>
    </Products>
    <Products>
      <ID>4</ID>
      <Name>Product4</Name>
      <Price>4000</Price>
      <CategoryID>2</CategoryID>
    </Products>
  </Categories>
</ProductsDataSet>

Třída XmlDataDocument

Jedním ze zajímavých prvků v ADO .NET spojující relační svět se světem hierarchickým je bez pochyb třída XmlDataDocument. Proč je tak zajímavá? Je tomu tak z důvodu, že díky ní je možné nad daty, které jsou obsaženy v objektu DataSet, provádět operace, které jsou možné provádět na XML daty.

Klepněte pro větší obrázek

Těmito operacemi nemám na mysli nic jiného než technologie XSL transformace či dotazy jazyka XPath. Třída XmlDataDocument je totiž odvozená od třídy XmlDocument se kterou jsme se již seznámili před nějakou dobou v tomto seriálu. To znamená, že s instancemi třídy XmlDataDocument jsme schopni provádět ty samé operace co s instancemi třídy XmlDocument s tím rozdílem, že jsme schopni asociovat objekt XmlDataDocument s objektem DataSet a tím využívat jeho data. Touto asociací tedy zařídíme, že objekt XmlDataDocument i objekt DataSet využívají jedna a ta samá data. To v praxi znamená, že pokud nějakým způsobem pozměníme data v objektu DataSet, tak se tato změna projeví i v XML, které představuje objekt XmlDataDocument.

//vytvoreni instance DataSetu
DataSet ds = new DataSet("EmployeesDataSet");
//vytvoreni tabulky se zamestnanci
DataTable employees = CreateEmployessTable();
//naplneni tabulky daty
CreateEmployees(employees);
ds.Tables.Add(employees);
//vytvoreni instance tridy XmlDataDocument asociovanou
//s nasim DataSetem
XmlDataDocument xmlDoc = new XmlDataDocument(ds);
//vypsani obsahu XML dokumentu
Console.WriteLine(xmlDoc.InnerXml);
//pridani noveho radku do tabulky
DataRow newRecord = employees.NewRow();
newRecord["firstName"] = "Novy";
newRecord["SurName"] = "Zamestnanec";
employees.Rows.Add(newRecord);
Console.WriteLine("Po zmene DataSetu :");
//pridany radek se projevi i v XML
Console.WriteLine(xmlDoc.InnerXml);

Asociaci s objektem DataSet můžeme provést buďto pomocí konstruktoru nebo také pomocí instanční vlastnosti DataSet třídy XmlDataDocument. A jak jsem psal o pár řádek výše, tak je možné nad objekty XmlDataDocument provádět například XSL transformace. Samozřejmě bychom mohli provádět XSL transformace například na souborem do kterého jsme zapsali XML reprezentaci objektu DataSet, ale instance třídy XmlDataDocument je objektem reprezentujícím tato XML data a tudíž je možné přímé provedené transformace.

//vytvoreni instance DataSetu
DataSet ds = new DataSet("EmployeesDataSet");
//vytvoreni tabulky se zamestnanci
DataTable employees = CreateEmployeeTable();
//naplneni tabulky daty
CreateEmployees(employees);
ds.Tables.Add(employees);
//vytvoreni instance tridy XmlDataDocument asociovanou
//s nasim DataSetem
XmlDataDocument xmlDoc = new XmlDataDocument(ds);
//provedeni XSL transformace nad dokumentem s daty o zamestnancich
XslTransform xslTrans = new XslTransform();
xslTrans.Load("stylesheet.xslt");
xslTrans.Transform(xmlDoc, null, Console.Out, null);

Příklady ke článku jsou k dispozici zde.

Témata článku: Software, Microsoft, Programování, Element, Vedlejší produkt

1 komentář

Nejnovější komentáře

  • Pavel Polívka 24. 11. 2007 13:55:41
    Programovou oflline verzi seriálu naleznete ke stažení na...
Určitě si přečtěte

11 tipů, jak efektivně a přesně sledovat počasí pomocí internetu

11 tipů, jak efektivně a přesně sledovat počasí pomocí internetu

** Sledujte počasí z více zdrojů a podrobněji, přesněji tak určíte, jaké počasí vás potká na dovolené ** Na webu najdete hromadu pokročilých předpovědí počasí, ale i specializované meteorologické služby ** Vybrali jsme 14 služeb na počasí, které se vám můžou hodit

23.  6.  2017 | Jakub Čížek | 19

Nejlepší program pro střih videa na doma: 9 video editorů, ze kterých si vyberete

Nejlepší program pro střih videa na doma: 9 video editorů, ze kterých si vyberete

** Pokročilé střihové programy pro neprofesionální využití stojí do 3 000 Kč, jsou ale i zdarma ** Podpora 4K, hromada editačních funkcí a efektové filtry jsou samozřejmostí ** Vybrali jsme 9 nejzajímavějších programů pro nejrozšířenější operační systém Windows

25.  6.  2017 | Stanislav Janů | 33

Herní počítač vs. Xbox One X: Kvalita obrazu není všechno

Herní počítač vs. Xbox One X: Kvalita obrazu není všechno

** Nový Xbox One X slibuje hraní ve 4K s HDR za 13 tisíc korun ** Aby stejnou kvalitu obrazu zvládl počítač, museli byste za něj dát minimálně dvakrát tolik ** Přesto herní počítače stále svůj smysl mají

24.  6.  2017 | Tomáš Holčík | 58


Aktuální číslo časopisu Computer

Bojujeme proti Fake News

Dva velké testy: fotoaparáty a NASy

Co musíte vědět o změně evropského roamingu

Radíme s výběrem základní desky