reklama

Poznáváme C# a Microsoft .NET 60. díl – ADO. NET – Implementace odpojených aplikací

Po několika dílech věnovaných implementaci aplikací pracujících s daty pomocí ADO .NET v takzvaném připojeném scénáři, se dnes poprvé zaměříme na druhý směr možného využití technologie ADO .NET, kterou je implementace odpojených aplikací. Dozvíme se něco o základním principu, který je v tomto druhu aplikací použit a také se seznámíme s třídami, které s odpojenými aplikacemi souvisí.

Odpojené aplikace

Jak jsem psal v díle uvádějícím do technologie ADO .NET, tak princip takzvaných odpojených aplikací, neboli aplikací pracujících s daty v odpojeném scénáři, je relativně novým přístupem k tvorbě aplikací pracujících s daty. V odpojeném scénáři není při práci s daty vždy aktivní připojení k datovému zdroji, ale je tomu právě naopak. V době, kdy má aplikace otevřené spojení k datovému zdroji, načte z něho data a vytvoří obraz datového zdroje do paměti.

S tímto obrazem následně aplikace pracuje, jako kdyby se jednalo a normální datový zdroj a po dokončení potřebných operací je opět otevřeno aktivní spojení k datovému zdroji a změny dat provedené v obraze jsou promítnuty do skutečného datového zdroje. To s sebou pochopitelně přináší výhodu v podobě znatelně menší komunikace mezi jednotlivými vrstvami aplikace, což oceníte hlavně v případech, kdy se tyto vrstvy nacházejí na jiných počítačích.

DataSet

Nyní již budu konkrétnější. Onen obraz datového zdroje v pamětí je v ADO .NET představován třídou DataSet, která je tedy stěžejní třídou pro odpojené aplikace v ADO .NET. K tomu, aby mohl DataSet vystupovat jako náhražka databáze disponuje schopnostmi uchovávat obrazy jedné nebo více tabulek. To ovšem není všechno.

Je možné pro jednotlivé tabulky definovat různá omezení (constraints), nebo také různé relace mezi jednotlivými tabulkami v DataSetu, což ve výsledku přináší opravdu velmi dobrou podporu pro vytvoření obrazu databáze pro práci v odpojeném prostředí. DataSet s sebou mimo jiné přináší další výhodu v podobě schopnosti zapsat se jako XML, což například umožňuje jej použít v aplikacích využívajících webové služby.

Na rozdíl od implementace připojených aplikací v ADO .NET, kde se pro čtení dat z datového zdroje používaly implementace rozhraní IDataReader, při jejichž používání je možné číst data pouze jedním směrem, je v případě využití třídy DataSet a s ním spojených tříd číst data bez jakýchkoli takovýchto omezení.

Ovšem při implementaci přístupu k datům použitím třídy DataSet nejsme omezeni pouze na čtení dat, ale je možné s daty provádět i změny, které jsou následně při připojení k datovému zdroji do něj promítnuty. Také na rozdíl od dříve probíraného připojeného scénáře, je možné, aby DataSet obsahoval reprezentaci dat z různých datových zdrojů, tedy že nějaké tabulky budou z jednoho datového zdroje a další tabulky zase z jiného datového zdroje.

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

Schéma objektu DataSet

K reprezentaci databázové tabulky v instanci třídy DataSet slouží třída DataTable, jejíž instance se nacházejí v kolekci DataTableCollection, představovanou vlastností Tables daného DataSetu. K vyjádření relací mezi objekty typu DataTable je k dispozici třída DataRelation a její instance jsou obsaženy v kolekci typu DataRelationCollection, kterého je vlastnost Relations třídy DataSet.

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

Schéma objektu DataTable

Samotná tabulka z datového zdroje je tedy v paměti reprezentována objekty typu DataTable. Stejně jako v databázi, tak i reprezentace tabulky v podobě objektu DataTable obsahuje sloupce různých datových typů. Jednotlivé sloupce jsou reprezentovány objekty typu DataColumn. Tyto reprezentace sloupců jsou obsaženy v kolekci DataColumnCollection. Tuto kolekci má každý objekt DataTable přístupnou skrze svou vlastnost Columns. Tak jako sloupce jsou i jednotlivé řádky v tabulce, představující záznamy, reprezentovány objekty. Tyto objekty jsou typu DataRow a nacházejí se v kolekci DataRowCollection, přístupnou pomocí vlastnosti Rows objektu DataTable.

Omezení vztahující se k jednotlivým sloupcům tabulky jsou představovány instancemi tříd, které jsou odvozeny od třídy Constraint a jsou agregovány v kolekci typu ConstraintCollection, kterého je vlastnost Constraints objektu DataTable.

Rozhraní IDataAdapter

Teď když jsme se seznámili se třídou DataSet a dalšími třídami s ní spojenými za účelem reprezentace dat a vztahů mezi nimi potřebujeme ještě vědět, jakým způsobem jsou tedy data z datového zdroje získávána respektive zpětně do datového zdroje aktualizována. Úlohu jakéhosi prostředníka mezi objektem DataSet a vlastním datovým zdrojem mají instance tříd implementujících rozhraní IDataAdapter.

Tyto rozhraní je stejně jako například v případě rozhraní IDbConnection implementováno na úrovni jednotlivých ADO .NET data providerů a umožňují naplnit DataSet daty z datového zdroje a také promítnout změny, které se provedly s daty v objektu DataSet zpět do datového zdroje. Konkrétní implementace typu IDataAdapter má asociované spojení k datovému zdroji a toto spojení využívá k získávání či úpravě dat. To jaká data jsou získána nebo jaký záznam je přidán/upraven/odebrán je dáno definicí jednotlivých příkazů, které jsou představovány pro nás již známým typem IDbCommand.

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

Funkce datového adaptéru

Příklad implementace

Po teoretickém úvodu již následuje příklad, který ukazuje možný způsob přístupu k datům pomocí kombinace DataSet a IDataAdapter.

/// <summary>
// Priklad na pouziti pristupu k datum pomoci kombinace
/// IDataAdapter + DataSet
/// </summary>
public class DataSetExample
{
  //pripojeni k databazi
  SqlConnection connection;
  //instance IDataAdapteru
  SqlDataAdapter adapter;
  //instance DataSetu
  DataSet ds;
  //prikaz na vyber dat
  SqlCommand selectCmd;
   
  /// <summary>
  /// Vytvori instanci tridy a provede nastaveni datovych objektu
  /// </summary>
  public DataSetExample()
  {
    connection = new SqlConnection(@"...");
    adapter = new SqlDataAdapter();
    ds = new DataSet();
    InitAdapter();
  }

  /// <summary>
  /// Naplni DataSet daty z tabulky employee
  /// </summary>
  public void LoadEmployees()
  {
    if (adapter != null)
    {
      adapter.Fill(ds, "emps");
    }
  }

  /// <summary>
  /// Inicializuje potrebne vlastnosti adapteru
  /// </summary>
  private void InitAdapter()
  {
    //definice vlastnosti SelectCommand adapteru, ktery urcuje
    //jaky prikaz je proveden pro ziskani dat
    selectCmd = new SqlCommand("select * from employee", connection);
    adapter.SelectCommand = selectCmd;
  }

  /// <summary>
  /// Vypise vsechny zaznamy z objektu datatable emps v datasetu
  /// </summary>
  public void PrintEmployees()
  {
    DataTable lTable = ds.Tables["emps"];
    //projit kazdy radek v tabulce
    foreach(DataRow lRow in lTable.Rows)
    {
      //projit kazdy sloupec v tabulce
      foreach(DataColumn lCol in lTable.Columns)
      {
        Console.Write(lRow[lCol] + " ");
      }
      Console.WriteLine();
    }
  }
}

/// <summary>
/// Trida na spusteni prikladu
/// </summary>
public class DataSetExampleMain
{
  public static void Run()
  {
    DataSetExample lInstance = new DataSetExample();
    lInstance.LoadEmployees();
    lInstance.PrintEmployees();
  }
}

Konstruktor třídy DataSetExample zajistí vytvoření potřebných objektů, kterými jsou objekt spojení (SqlConnection), instance třídy DataSet a také vytvoření instance třídy SqlDataAdapter tedy implementace rozhraní IDataAdapter pro MS SQL server. Po vytvoření těchto objektů je nakonec zavolána privátní metoda InitAdapter, která zajistí inicializaci vlastnosti SelectCommand objektu SqlDataAdapter.

Příkaz asociovaný s touto vlastností je použit pro naplnění objektu DataSet daty. Naplnění objektu DataSet se děje v těle metody LoadEmployees, kde je na objektu SqlDataAdapter zavolána metoda Fill, jíž je předán objekt DataSet, který má být naplněn a také je specifikován název objektu DataTable, který bude v objektu DataSet vytvořen a do kterého budou zapsána získaná data. Po provedení této akce je tedy v objektu DataSet jeden objekt typu DataTable obsahující záznamy vrácené po provedení dotazu asociovaným s vlastností SelectCommand datového adaptéru.

Vypsání těchto záznamů je prováděno v metodě PrintEmployees, kde je pomocí cyklu iterováno kolekcí DataRowCollection tabulky z objektu DataSet a pro každý řádek v ní obsažený je vypsána hodnota všech sloupců. Toho je dosaženo použitím indexeru třídy DataRow, který vrací hodnotu jednotlivé buňky na základě předaného sloupce. Všimněte si, že jsem se nikde nezabýval otevíráním či zavíráním připojení k databázi a to z důvodu, že tyto operace již provádí datový adaptér.

Implementační příklad ke článku naleznete zde.

Příští díl se budeme již podrobněji zabývat praktickou implementací odpojených aplikací.

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

1 komentář

Nejnovější komentáře

  • Pavel Polívka 24. 11. 2007 13:51:53
    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 | 98

ASUS ZenBook 3 se začal prodávat v Česku. Je ve všem lepší než MacBook, ale bude to stačit?

ASUS ZenBook 3 se začal prodávat v Česku. Je ve všem lepší než MacBook, ale bude to stačit?

** Novinka od Asusu míří přímo proti MacBooku od Applu ** Nabídne daleko více výkonu za stejné peníze

2.  12.  2016 | David Polesný | 139

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 | 73


reklama