reklama

Poznáváme C# a Microsoft .NET 65. – ADO .NET – stavitel dotazů a ukládání DataSetu do XML

Dnešní díl si klade za úkol čtenáře seznámit se zajímavým způsobem tvorby příkazů pro datový adaptér a také jak je možné využít formát XML pro uložení či načtení objektu DataSet.

Stavitel dotazů

V minulém díle, kdy jsme se zaobírali datovými adaptéry, jsme zjistili, že pro obousměrnou synchronizaci datové sady, tedy objektu DataSet se souvisejícím datovým zdrojem je potřebné použit datový adaptér, který má správně definovány všechny čtyři příkazy (SelectCommand, InsertCommand, UpdateCommand a DeleteCommand). To ovšem, jak jistě víte, znamená určité úsilí, protože pro příkazy upravující související datový zdroj jsou parametrické a je potřeba uvést mapování pro každý sloupec. Pokud se budeme chtít definici těchto příkazů efektivně vyhnout, využijeme takzvaného stavitele dotazů.

Stavitel dotazů je pro každý specifický ADO .NET data provider představován jinou třídou jak je již v ADO .NET zvykem, avšak na rozdíl od ostatních součástí ADO .NET neexistuje společné rozhraní (typu IDataAdapter, IDbCommand..), které je pro konkrétní datového poskytovatele implementováno. Takže v základní knihovně tříd nalezneme stavitelé dotazů pro základní datové poskytovatele, kterými jsou SqlCommandBuilder, OracleCommandBuilder, OleDbCommandBuilder a OdbcCommandBuilder.

Pokud stavitele dotazů asociujeme s datovým adaptérem, tak je stavitel schopen vygenerovat příkazy InsertCommand, UpdateCommand a DeleteCommand asociovaného datového adaptéru. Jediné úsilí, které musíme při vytváření adaptéru vyvinout je definice vlastnosti SelectCommand. Proč je tomu tak? Stavitel totiž použije výsledkovou sadu získanou pomocí příkazu SelectCommand a na základě schématu této sady vygeneruje ostatní dotazy. Pomocí stavitele dotazů jsme tedy schopni velmi zrychlit vývoj naší aplikace, která pracuje z daty v odpojeném režimu. Následující zdrojový kód představuje příklad na použití třídy SqlCommandBuilder, což je stavitel dotazů pro MS SQL Server.

public sealed class CommandBuilderExample
{
  public static void Run()
  {
    SqlConnection connection = new SqlConnection(@"...");
    SqlDataAdapter adapter = GetAdapter(connection);
    DataSet dataset = new DataSet();
    //naplnime dataset daty
    adapter.Fill(dataset, "employees");
   
    DataRow record = dataset.Tables["Employees"].Rows[0];
    record["FirstName"] = "Upravene jmeno";

    //tento kod by bez pouziti stavitele dotazu skoncil chybou
    adapter.Update(dataset, "employees");
}

  private static SqlDataAdapter GetAdapter(SqlConnection connection)
  {
    SqlDataAdapter result = new SqlDataAdapter();
    result.SelectCommand = new SqlCommand("select * from employee",connection);
    //asociace stavitele s datovym adapterem
    SqlCommandBuilder builder = new SqlCommandBuilder(result);
    return result;
  }
}

Jak vidíte, tak využití stavitele dotazů je velmi jednoduché, stačí pouze asociovat stavitele s daným datovým adaptérem, což provedeme buď konstruktorem, jak je tomu v našem příkladu a nebo nastavením instanční vlastnosti DataAdapter. A pokud má daný datový adaptér nastavenou vlastnost SelectCommand, můžeme již směle volat metodu Update našeho adaptéru a vše ostatní můžeme ponechat na staviteli. Příkazy jsou stavitelem sestrojeny v případě prvního volání metody Update našeho adaptéru. Stavitel se totiž po asociaci s datovým adaptérem stane odběratelem (pozorovatelem) události RowUpdating datového adaptéru, která je vyvolávána při průběhu metody Update a tak je stavitel schopen včas zareagovat vygenerováním příslušných příkazů. Používá k tomu své metody GetInsertCommand, GetUpdateCommand a GetDeleteCommand a jelikož jsou tyto metody veřejné, nic nám nebrání je ze svého kódu v případě potřeby využít. Po spuštění následujícího kódu získáte výpis vygenerovaných parametrických dotazů.

SqlConnection connection = new SqlConnection(@"...");
//jedine co je potreba nastavit je vlastnost SelectCommand
SqlDataAdapter adapter = new SqlDataAdapter("select * from employee", connection);
SqlCommandBuilder builder = new SqlCommandBuilder(adapter);
     
Console.WriteLine("Insert command : {0}", builder.GetInsertCommand().CommandText);
Console.WriteLine("Update command : {0}", builder.GetUpdateCommand().CommandText);
Console.WriteLine("Delete command : {0}", builder.GetDeleteCommand().CommandText);

I když nám při práci v odpojeném prostředí může stavitel dotazů ušetřit spoustu práce je třeba splnit také určité podmínky. Definovaný příkaz představující SelectCommand daného datového adaptéru, musí vracet výsledkovou sadu v níž alespoň jeden sloupec představuje primární klíč nebo sloupec s unikátními hodnotami (v našem případě sloupec ID), jinak by pokus o sestavení příkazu UpdateCommand nebo DeleteCommand skončilo vyhozením výjimky.

Kromě této věci je dobré vědět, že před prvním vygenerováním jakéhokoli příkazu pomocí stavitele je proveden příkaz SelectCommand datového adaptéru nad datovým zdrojem za účelem získání schématu tabulky, což samozřejmě znamená určitou ztrátu výkonu, kterou je v určitých případech dobré brát v potaz.

DataSet a XML

Jedním ze zásadních cílů návrhu komponenty ADO .NET bylo její silné spojení s formátem XML. Třída DataSet, jakožto stěžejní prvek ADO .NET, disponuje vlastností zapsat se do formátu XML a naopak také se z XML načíst. Díky této vlastnosti je mimochodem například možné používat instance třídy DataSet u aplikací založených na XML webových službách. DataSet za účelem uložení se obsahuje metodu WriteXml a za účelem načtení se metodu ReadXml. XML představující DataSet může být obecně zapsán do jakéhokoli datového proudu. Informace zapsané do XML jsou bohaté. Nejen, že jsou zapsány jednotlivé objekty DataTable, ale případně i relace mezi nimi a také je možné do XML datového proudu zapsat informace popisující schéma daného objektu DataSet. Následující příklad ukazuje, jak je možné zapsat obsah objektu DataSet do XML a následně tento obsah načíst.

/// <summary>
/// Priklad na export/import DataSetu do/z XML
/// </summary>
public class DataSetXML
{
  public static void Run()
  {
    //jmeno datasetu se projevi v XML
    DataSet ds = new DataSet("DataSetZive");
    //vytvoreni tabulky
    DataTable employeesTable = CreateEmployeeTable();
    //naplneni tabulky
    CreateEmployees(employeesTable);
    ds.Tables.Add(employeesTable);
    //zapsani do XML
    ds.WriteXml("employees.xml");
    //vymazani obsahu datasetu
    ds.Clear();
    Console.WriteLine("Pocet zaznamu v tabulce employees : {0}", ds.Tables["employees"].Rows.Count);
    //nacteni obsahu z XML souboru
    ds.ReadXml("employees.xml");
    Console.WriteLine("Pocet zaznamu v tabulce employees po precteni XML: {0}", ds.Tables["employees"].Rows.Count);
  }

  static DataTable CreateEmployeeTable()
  {
    DataTable table = new DataTable("employees");
    DataColumn idCol = table.Columns.Add("ID", typeof(int));
    table.Columns.Add("FirstName", typeof(string));
    table.Columns.Add("SurName", typeof(string));
    idCol.Unique = true;
    idCol.AutoIncrement = true;
    idCol.AllowDBNull = false;
    return table;
  }

  static void CreateEmployees(DataTable table)
  {
    DataRow pusRow = table.NewRow();
    pusRow["FirstName"] = "Petr";
    pusRow["SurName"] = "Pus";

    DataRow racekRow = table.NewRow();
    racekRow["FirstName"] = "Michal";
    racekRow["SurName"] = "Racek";

    table.Rows.Add(pusRow);
    table.Rows.Add(racekRow);
  }
}

To, že jsem využil přetížené verze konstruktoru třídy DataSet, která přijímá jméno nově vznikající instance, se projeví ve výsledném XML jak za chvíli uvidíme. Metoda WriteXml také existuje v několika přetížených verzích. Já jsem v příkladu použil jednoduchou verzi přijímající jméno souboru do kterého bude výsledný XML datový proud zapsán, ovšem je možné využít i jinou přetíženou verzi této metody a zapsat DataSet do jakéhokoli jiného typu datového proudu. Stejně je tomu i v případě metody ReadXml. Soubor XML by měl po spuštění tohoto příkladu obsahovat následující obsah.

<?xml version="1.0" standalone="yes"?>
<DataSetZive>
  <employees>
    <ID>0</ID>
    <FirstName>Petr</FirstName>
    <SurName>Pus</SurName>
  </employees>
  <employees>
    <ID>1</ID>
    <FirstName>Michal</FirstName>
    <SurName>Racek</SurName>
  </employees>
</DataSetZive>

Hlavním elementem je námi specifikovaný název objektu DataSet a po té následuje vždy element se jménem objektu DataTable v němž jsou jednotlivé složky záznamu (DataRow) z tohoto objektu.

Jak jsem zmínil o pár řádek výše tak kromě obsažených dat a případných relací mezi tabulkami je možné do XML zapsat i údaje o schématu objektu DataSet. Toho docílíme použitím přetížené verze metody WriteXml, které přijímá kromě cíle zápisu, také hodnotu z výčtu XmlWriteMode. Také je možné analogickým způsobem zařídit načtení schématu objektu DataSet z XML.

//zapsani do XML
ds.WriteXml("employees.xml", XmlWriteMode.WriteSchema);
...
//nacteni obsahu z XML souboru
ds.ReadXml("employees.xml",XmlReadMode.ReadSchema);

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

Témata článku: Software, Microsoft, Programování, Adapter, Command

1 komentář

Nejnovější komentáře

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

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

** V Brně byl velký výpadek služeb UPC ** Důvodem je překopnutý páteřní kabel ** V některých lokalitách služby stále nefungují

5.  12.  2016 | Jakub Čížek | 103

17 expertek Microsoftu předpovědělo rok 2027. Splní se alespoň něco?

17 expertek Microsoftu předpovědělo rok 2027. Splní se alespoň něco?

** Zmizí klasické vyhledávače ** Budeme programovat buňky ** Kvantové počítače překonají šifry

6.  12.  2016 | Jakub Čížek | 36

11 tipů na dobrý stolní počítač: od základu po herní mašiny

11 tipů na dobrý stolní počítač: od základu po herní mašiny

** Postavte si stolní počítač! Máme pro vás 11 vzorových sestav s rozpisem komponent ** Většina tipů cílí na hráče, věnujeme se ale i základnímu PC a počítačům na střih videa ** Nadělte si nový počítač třeba pod stromeček

5.  12.  2016 | Adam Kahánek | 74

Nejlepší notebooky nad 20 tisíc: poradíme, které teď chcete

Nejlepší notebooky nad 20 tisíc: poradíme, které teď chcete

** V notebooku s cenou nad 20 tisíc nesmí chybět kvalitní displej a rychlé úložiště ** Za dalších deset tisíc můžete dostat navíc styl nebo výkonnější komponenty ** Vybírat můžete z různých velikostí i konstrukcí

8.  12.  2016 | Stanislav Janů | 84


reklama