Poznáváme C# a Microsoft .NET 56. díl – ADO .NET - Implementace připojených aplikací

V tomto díle navážeme na díl předchozí a podíváme se trochu blíže na možnosti použití typu IDataReader a také jak je možné využít typ IDbCommand v připojeném scénáři přístupu k datovému zdroji.
Poznáváme C# a Microsoft .NET 56. díl – ADO .NET - Implementace připojených aplikací

Další možnosti typu IDataReader

V minulém díle již byla ukázána implementace přístupu k datům pomocí typu IDataReader, kde se k hodnotám pro jednotlivé sloupce v řádku přistupovalo pomocí indexeru, který představoval vlastnost Item definovanou na rozhraní IDataRecord (jež rozhraní IDataReader rozšiřuje).

Kromě této vlastnosti definuje rozhraní IDataRecord i poměrně početnou sadu metod, které vracejí tyto hodnoty již jako konkrétní typy CTS (Common Type System), takže například metoda GetInt32 vrací hodnotu daného sloupce aktuálního řádku přetypovanou na typ Int32, tedy typ int jazyka C#, samozřejmě pokud je takovéto přetypování možné. Těchto metod využijeme v případě, kdy přesně víme, jakých typů jsou jednotlivé sloupce v databázové tabulce.

/// <summary>
/// Priklad na pouziti Get* metod implementace rozhrani IDataReader
/// </summary>
public class DataReaderExample1
{
  public static void PrintAllEmployees()
  {
    IDbConnection lConnection = new SqlConnection(@"data source=`dellak\sql1`;initial catalog=`zive`;integrated security=`sspi`");
    IDbCommand lCommand = new SqlCommand("select * from employee");
    lCommand.Connection = lConnection;
    IDataReader lReader = null;
    try
    {
      lConnection.Open();
      lReader = lCommand.ExecuteReader();
      //pri cteni budou hodnoty sloupcu ziskany pomoci specifickych metod
      while (lReader.Read())
      {
        //id
        int lId = lReader.GetInt32(0);
        //jmeno
        string lFirstName = lReader.GetString(1);
        //prijmeni
        string lSurName = lReader.GetString(2);
        //datum narozeni
        DateTime lBirthDate = lReader.GetDateTime(3);
        Console.WriteLine("{0} - {1} - {2} - {3}", lId, lFirstName, lSurName, lBirthDate);
      }
    }
    catch(SqlException ex)
    {
    Console.WriteLine("Nastala vyjimka : {0}", ex.ToString());
    }
    finally
    {
      if (lReader != null && !lReader.IsClosed)
      {
        lReader.Close();
      }
      if (lConnection != null && !lConnection.State.Equals(ConnectionState.Closed))
      {
        lConnection.Close();
      }
    }
  }
}

Kromě těchto metod vracejících hodnoty o specifických typech je na rozhraní IDataReader definována i metoda GetValue, která vrací hodnotu typu System.Object a po té je možné ji explicitně přetypovat, což je v podstatě stejná funkčnost jako pří použití již známého indexeru (vlastnost Item). Pokud chceme získat hodnoty všech sloupců pro aktuální řádek je možné využít metody GetValues a pomocí ní dostaneme pole objektů typu System.Object obsahující kýžené hodnoty.

V příkladu je při zavírání objektu IDataReader, kromě kontroly toho jestli byl objekt inicializován (test na null) také využito vlastnosti IsClosed, podle které zjistíme jestli je již reader uzavřen (podle názvu nečekaně). Také při zavíraní připojení k databázi je mimo kontroly na hodnotu null přečtena vlastnost State, jež je typu ConnectionState, což je výčet představující možné stavy daného přípojení. Při kontrole se ověří jestli již není spojení uzavřeno.

Uzavření spojení spolu s uzavřením data readeru

V častých implementačních scénářích budeme spojení k databázi uzavírat ihned po zavření objektu typu IDataReader, kdy už jsou data přečtena tak jak je prováděno v uvedených příkladech.

Existuje možnost jak zařídit, aby byla konexe k databázi uzavřena ve chvíli, kdy je uzavřen IDataReader. Metoda ExecuteReader typu IDbCommand, existuje totiž v přetížené verzi přijímající parametr typu CommandBehavior. Pomocí tohoto výčtu můžeme definovat příznaky (je na něj použit atribut Flags), které ovlivní chování IDataReaderu. Příznak, který nám zajistí požadovanou operaci, tedy uzavření spojení spolu s IDataReaderem je hodnota CloseConnection.

/// <summary>
/// Ukazka pouziti uzitecne pretizene verze metody ExecuteReader implementace
/// rozhrani IDbCommand
/// </summary>
public class DataReaderExample2
{
  public static void PrintAllEmployees()
  {
    IDbConnection lConnection = new SqlConnection(@"data source=`dellak\sql1`;initial catalog=`zive`;integrated security=`sspi`");
    IDbCommand lCommand = lConnection.CreateCommand();
    lCommand.CommandText = "select * from employee";
    IDataReader lReader = null;
    try
    {
      lConnection.Open();
      //chceme, aby bylo pripojeni zavreno spolu se zavrenim readeru
      lReader = lCommand.ExecuteReader(CommandBehavior.CloseConnection);
      while (lReader.Read())
      {
        //operace cteni dat z vysledkove sady
      }
    }
    finally
    {
      if (lReader != null && !lReader.IsClosed)
      {
        //zavreni pripojeni k databazi je provedeno
        //po zavreni readeru
        lReader.Close();
      }
    }
    Console.WriteLine("Stav pripojeni : {0}", lConnection.State);
  }
}

Další využití typu IDbCommand

Prozatím jsme implementovali pouze situace, kdy jsme data četli. Jak ale v připojené aplikaci, kromě již známého čtení pomocí IDataReaderu, data v databázi upravovat? Velmi jednoduše pomocí instancí tříd implementujících rozhraní IDbCommand. K vyvolání příkazu stačí jen použít metody ExecuteNonQuery. Tato metoda je primárně určena pro vykonávání sql příkazů INSERT, UPDATE nebo DELETE.

/// <summary>
/// Ukazka pouziti implementace rozhrani IDbCommand pro vlozeni
/// radku do databaze v pripojene aplikaci
/// </summary>
public class InsertingDataExample
{
  public static void Run()
  {
    InsertRow("Petr", "Fisar", DateTime.Now.AddYears(-20));
  }

  public static void InsertRow(string firstName, string surName, DateTime birthDate)
  {
    IDbConnection lConnection = new SqlConnection(@"data source=`dellak\sql1`; initial catalog=`zive`; integrated security=`sspi`");
    IDbCommand lCommand = lConnection.CreateCommand();
    //vytvoreni sql prikazu pro vlozeni radku
    lCommand.CommandText = String.Format("insert into employee (FirstName, SurName, BirthDate) values (`{0}`,`{1}`,`{2}`)", firstName, surName, birthDate);
    Console.WriteLine(lCommand.CommandText);
    try
    {
      lConnection.Open();
      //spusteni prikazu
      lCommand.ExecuteNonQuery();
      Console.WriteLine("Zaznam byl pridan");
    }
    catch(SqlException ex)
    {
      Console.WriteLine("Nastala vyjimka : {0}", ex);
    }
    finally
    {
      if (lConnection != null && !lConnection.State.Equals(ConnectionState.Closed))
      {
        lConnection.Close();
      }
    }
  }
}

Na rozdíl do metody ExecuteReader vracející odkaz na IDataReader užívaný ke čtení výsledkové sady, tak metoda ExecuteNonQuery vrací pouze číslo indikující kolik záznamů v datovém zdroji bylo příkazem ovlivněno. To se může hodit hlavně v případě UPDATE či DELETE příkazů.

/// <summary>
/// Priklad na ukazku zjisteni poctu zasazenych radku dotazem
/// vyvolanym pres metodu ExecuteNonQuery typu IDbCommand
/// </summary>
public class DeletingDataExample
{
  public static void DeleteRow(int id)
  {
    IDbConnection lConnection = new SqlConnection(@"data source=`dellak\sql1`; initial catalog=`zive`; integrated security=`sspi`");
    IDbCommand lCommand = lConnection.CreateCommand();
    lCommand.CommandText = String.Format("delete from employee where ID={0}", id);
    try
    {
      lConnection.Open();
      //metoda vraci pocet zasazenych radku
      int lAffected = lCommand.ExecuteNonQuery();
      Console.WriteLine("Pocet zasazenych radku : {0}", lAffected);
    }
    catch(SqlException ex)
    {
      Console.WriteLine("Nastala vyjimka : {0}", ex);
    }
    finally
    {
      if (lConnection != null && !lConnection.State.Equals(ConnectionState.Closed))
      {
        lConnection.Close();
      }
    }
  }
}

Nezajímavou také není metoda ExecuteScalar tohoto typu. Tato metoda nalezne jistě uplatnění v případě použití různých SQL agregačních funkcí. Návratovou hodnotou této metody je totiž první sloupec prvního řádku ze získané výsledkové sady. Takže pokud bychom chtěli zjistit počet evidovaných zaměstnanců v naší databázi, mohli bychom pro vyřešení tohoto požadavku použít následující implementací.

/// <summary>
/// Priklad na vyuziti metody ExecuteScalar typu IDbCommand
/// </summary>
public class SelectCountExam
{
  public static void PrintCount()
  {
    IDbConnection lConnection = new SqlConnection(@"data source=`dellak\sql1`; initial catalog=`zive`; integrated security=`sspi`");
    IDbCommand lCommand = lConnection.CreateCommand();
    //sql dotaz vrati pocet vsech radku v tabulce
    lCommand.CommandText = "select count(*) from employee";
    try
    {
      lConnection.Open();
      object lResult =  lCommand.ExecuteScalar();
      Console.WriteLine("Pocet evidovanych zamestnancu : {0}", lResult);
    }
    catch(SqlException ex)
    {
    Console.WriteLine("Nastala vyjimka : {0}", ex);
    }
    finally
    {
      if (lConnection != null && !lConnection.State.Equals(ConnectionState.Closed))
      {
        lConnection.Close();
      }
    }
  }
}

Příklady ke článku si můžete stáhnout zde.

Příště se ještě budeme zabývat problematikou implementace připojených aplikací a podíváme se například na parametrizované příkazy.

Témata článku: Software, Microsoft, Programování, Public, Catch, Item

2 komentáře

Nejnovější komentáře

  • Pavel Polívka 24. 11. 2007 13:49:29
    Programovou oflline verzi seriálu naleznete ke stažení na...
  • fantasy 16. 1. 2006 11:12:30
    Nevim, jestli se na to dostanete, presto bych Vas Petre poprosil v...
Určitě si přečtěte

Pojďme programovat elektroniku: Postavíme si titěrnou Wi-Fi meteostanici s lepším teploměrem než Netatmo

Pojďme programovat elektroniku: Postavíme si titěrnou Wi-Fi meteostanici s lepším teploměrem než Netatmo

** Dnes se podíváme na maličkou Wi-Fi destičku Wemos D1 mini ** A připojíme k ní barometrický a teplotní shield ** Poběží na ní web a nabídne i JSON API

18.  6.  2017 | Jakub Čížek | 27

Jak vybrat monitor k počítači: nenechte se zlákat nepodstatnými parametry

Jak vybrat monitor k počítači: nenechte se zlákat nepodstatnými parametry

** Na jaké parametry se zaměřit a kde vás výrobci chtějí nachytat ** Monitory se stále více specifikují pro konkrétní určení ** Náročný hráč nebo profesionální grafik mají různé požadavky

20.  6.  2017 | Tomáš Holčík | 31

Dlouhodobý test HTC Vive: co vám recenze o virtuální realitě neřeknou

Dlouhodobý test HTC Vive: co vám recenze o virtuální realitě neřeknou

** Ani hry se sebelepší grafikou vás nevtáhnou tolik, jako ve virtuální realitě ** Pro sledování filmů není VR ani zdaleka ideální ** I první generace je skvělá, stále však působí jako prototyp

20.  6.  2017 | Stanislav Janů | 20

Jak unikají informace o nových iPhonech? Třeba podprsenkami čínských pracovnic

Jak unikají informace o nových iPhonech? Třeba podprsenkami čínských pracovnic

** Na černém trhu mohou zaměstnanci továren za kradené součástky inkasovat částku ve výši ročního platu ** Velké množství informací je vyneseno i z centrály Applu ** Díly jsou pašovány v botách, podprsenkách i odpadem

21.  6.  2017 | Stanislav Janů | 22


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