Poznáváme C# a Microsoft. NET 61. díl – ADO .NET – DataTable

Po úvodu do světa odpojených datových aplikací se dnes budeme zabývat bližším pohledem na objekt DataTable. Mimo jiné si řekneme něco o jeho úloze a jakými způsoby je možné tento objekt vytvořit.

Jak jsme se dozvěděli v minulém díle, stěžejním typem při implementaci odpojených datových aplikací je DataSet. K tomu, aby mohl DataSet v paměti reprezentovat datový zdroj použivá jeden nebo více objektů typu DataTable. Objekty typu DataTable slouží k reprezentaci jedné tabulky dat v paměti.

Pravděpodobně nejčastěji jsou objekty tohoto typu získávány dynamicky za použití zmíněného objektu DataSet v kombinaci s příslušnou implementací rozhraní IDataAdapter, ale rozhodně není výjimkou, že jsou objekty DataTable vytvářeny programově (vlastním kódem) a následně například vázány na nějaký visuální prvek (ať už v ASP .NET aplikaci nebo Windows forms aplikaci). My se dnes budeme v rámci poznávání tohoto objektu zabývat způsobem druhým, tj. že si objekt DataTable budeme vytvářet programově, abychom lépe pochopili vlastnosti jednotlivých stavebních prvků tvořící objekt DataTable.

Schéma objektu DataTable

Objekty typu DataColumn

Jak ukazuje obrázek výše, instance třídy DataColumn reprezentují jeden sloupec v instanci třídy DataTable. To znamená, že kolekce těchto sloupců, kterou je typ DataColumnCollection, svázaná s konkrétním objektem DataTable vlastně určuje schéma tabulky, kterou objekt DataTable reprezentuje. Předpokládejme, že bychom měli tabulku Employee obsahující tři sloupce (ID, FirstName, SurName) a chtěli bychom programově vytvořit reprezentaci této tabulky v paměti. Tak vytvoříme tři instance třídy DataColumn se specifickými vlastnostmi a vložíme je do kolekce DataColumnCollection objektu DataTable skrze vlastnost Columns.

Zmíněných vlastností je celá řada a to dovoluje typu DataColumn chovat se jako sloupec ve skutečné tabulce v databázi (to ostatně v případě získání objektu DataTable pomocí DataSet + IDataAdapter dělá), takže je možné sloupci nastavit, že jeho hodnota má být v rámci objektu DataTable unikátní či že má být jeho hodnota s každým novým záznamem automatický zvětšena atd. Následující příklad vytvoří objekt typu DataColumn, nastaví mu některé vlastnosti a přiřadí jej k objektu DataTable.

/// <summary>
/// Priklad na vytvoreni objektu DataColumn
/// </summary>
public class BuildingDataColumn
{
  public static void BuildColumn()
  {
    //vytvoreni objektu DataTable
    DataTable lTable = new DataTable();
    //vytvoreni objektu DataColumn
    DataColumn lFirstNameCol = new DataColumn();
    //nastaveni vlastnosti
    lFirstNameCol.ColumnName = "FirstName";
    lFirstNameCol.ReadOnly = true;
    lFirstNameCol.DataType = typeof(String);
    lFirstNameCol.DefaultValue = "default";
    //prirazeni do kolekce sloupcu objektu DataTable
    lTable.Columns.Add(lFirstNameCol);

    Console.WriteLine("Tabulka obsahuje {0} sloupcu", lTable.Columns.Count);
  }
}

Sloupci, který je v příkladu vytvořen, je pomocí vlastnosti ColumnName nastaveno jméno sloupce, pod kterým sloupec bude vystupovat v kolekci DataColumnCollection. Vlastností ReadOnly určíme, zda-li je hodnota obsažená v daném sloupci pouze pro čtení. Datový typ sloupce je určen vlastností DataType a jako poslední vlastností v příkladu je nastavena vlastnost DefaultValue, určující jaká bude výchozí hodnota v daném sloupci po přidání nového záznamu. Po nastavení vlastností je sloupec přidán do kolekce sloupců vytvořeného objektu DataTable pomocí metody Add na typu DataColumnCollection.

Kdybychom chtěli zařídit, aby hodnoty sloupce v rámci objektu DataTable museli být unikátní a ještě k tomu se hodnota ve sloupci s každým novým záznamem do tabulky automaticky zvyšovala, učinili bychom to následujícím způsobem.

public static void BuildColumnWithPK()
{
  DataTable lTable = new DataTable();
  //vytvoreni noveho sloupce do kolekce tabulky
  DataColumn lIDCol = lTable.Columns.Add("ID", typeof(int));
  //zakazani null hodot
  lIDCol.AllowDBNull = false;
  //hodnoty nesmi byt duplikatni
  lIDCol.Unique = true;
  //nastaveni automatickeho zvysovani hodnoty sloupce
  lIDCol.AutoIncrement = true;
  //nastaveni pocatecni hodnoty sloupce
  lIDCol.AutoIncrementSeed = 100;
  //nastaveni kroku zvysovani
  lIDCol.AutoIncrementStep = 2;
}

Po nastavení těchto vlastností sloupci, bude mít první záznam v tomto sloupci hodnotu 100, druhý záznam 102, třetí 104 atd. Všimněte si způsobu vložení nového sloupce, kdy je využito toho, že metoda Add typu DataColumnCollection vrací odkaz na přidaný sloupec a následně až po přidání do kolekce jsou tomuto sloupci nastaveny vlastnosti.

Objekty typu DataRow

Jak jsme se dozvěděli na předchozích rádcích, tak schéma tabulky, která je v paměti představována objektem DataTable, je tvořeno kolekcí objektů typu DataColumn, kterou si ve formě instance třídy DataColumnCollection interně uchovává daný DataTable objekt.

Pokud máme takto definováno schéma, můžeme již směle přidávat záznamy do naší tabulky. K tomu je nám k dipozici třída DataRow jejiž instance představují jednotlivé záznamy v objektu DataTable. Jinými slovy pokud chceme přidat do reprezentace tabulky 10 záznámů, vytvoříme 10 instancí třídy DataRow a přidáme je do kolekce řádků dané instance třídy DataTable. Stejně jako v případě objektů DataColumn má objekt DataTable interní kolekci k uchovávání instancí třídy DataRow. Tato kolekce je přístupná skrze vlastnost Rows objektu DataTable a je typu DataRowCollection. Následující zdrojový kód ukazuje použití tohoto objektu.

/// <summary>
/// Priklad na praci s objekty DataRow
/// </summary>
public class ManagingDataRows
{
  public static void Run()
  {
    //vytvoreni tabulky
    DataTable lTable = new DataTable();
    lTable.Columns.Add("FirstName", typeof(String));
    lTable.Columns.Add("SurName", typeof(String));
    //vytvoreni novych zaznamu
    DataRow lRow1 = lTable.NewRow();
    DataRow lRow2 = lTable.NewRow();
    lRow1["FirstName"] = "Jan";
    lRow1["SurName"] = "Novak";
    lRow2["FirstName"] = "Petr";
    lRow2["SurName"] = "Pus";
    //pridani zaznamu do tabulky
    lTable.Rows.Add(lRow1);
    lTable.Rows.Add(lRow2);
    Console.WriteLine("Pocet radku v tabulce : {0}", lTable.Rows.Count);
    //vyjmuti prvniho zaznamu
    lTable.Rows.RemoveAt(0);
    Console.WriteLine("Pocet radku v tabulce : {0}", lTable.Rows.Count);
  }
}

Práce s objekty typu DataRow je trochu rozdílná od práce s objekty typu DataColumn, protože v případě objektu DataRow nevytváříme nové instance přímo použitím konstruktoru tohoto typu, ale odpovědnost za vytvoření nové instance nese objekt DataTable do něhož chceme záznam přidat. Toho dosáhneme použitím metody NewRow.

Takto nově vytvořený objekt DataRow má schéma dané objektem DataTable, který jej vytvořil. Hodnoty pro jednotlivé sloupce přiřadíme pomocí indexeru typu DataRow a nakonec záznamy přidáme do tabulky pomocí metody Add kolekce DataRowCollection příslušného objektu DataTable. Po přídání obou těchto nových záznamů je první záznam vyjmut pomocí metody RemoveAt na kolekci DataRowCollection.

Příklad na konec

Následující, poslední příklad tohoto článku vytvoří nový objekt DataTable, naplní jej daty a nakonec obsažená data vypíše.

/// <summary>
/// Priklad na praci s objektem DataTable
/// </summary>
public class BuildingTable
{
  public static void RunBuilding()
  {
    DataTable lTable = BuildTable();
    FillTable(lTable);
    PrintTable(lTable);
  }

  //vytvori objekt DataTable
  static DataTable BuildTable()
  {
    DataTable lTable = new DataTable("Employees");
    DataColumn lIDCol = lTable.Columns.Add("ID", typeof(Int32));
    lIDCol.AllowDBNull = false;
    lIDCol.Unique = true;
    lIDCol.AutoIncrement = true;
    lTable.Columns.Add("FirstName", typeof(String));
    lTable.Columns.Add("SurName", typeof(String));
    return lTable;
  }

  //vytvori zaznamy do objektu DataTable
  static void FillTable(DataTable table)
  {
    DataRow lPusRow = table.NewRow();
    lPusRow["FirstName"] = "Petr";
    lPusRow["SurName"] = "Pus";

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

    table.Rows.Add(lPusRow);
    table.Rows.Add(lRacekRow);
  }
  //vypise obsah objektu DataTable
  static void PrintTable(DataTable table)
  {
    foreach(DataRow lRow in table.Rows)
    {
      foreach(DataColumn lCol in table.Columns)
      {
        Console.Write("{0} - {1}, ", lCol.ColumnName, lRow[lCol]);
      }
      Console.WriteLine();
    }
  }
}

Příklady ke článku naleznete zde.

Diskuze (9) Další článek: Procesor Cell pro Playstation 3 použije IBM i v serverech

Témata článku: , , , , , , , , , , , , , , ,