Programavimas

Čia bus rašoma knyga apie programavimą.

.NET Programavimas

.NET Programavimas.

ADO.NET Programavimas naudojant interfeisus

Šio straipsnio tikslas yra parodyti kaip galima dirbti su ADO.NET naudojant System.Data interfeisus. Pvz. implementuojant System.Data.IDbConnection interfeisą sukurtos visos ADO.NET Connection klasės, pvz.: SqlConnection, OleDbConnection, OdbcConnection, MySqlConnection, OracleConnection ir t.t... Tokia pati situacija yra ir su ADO.NET komandų objektais, jos visos yra nuveldėtos nuo System.Data.IDbCommand interfeiso.

Daugelis programuotojų inicializuoja šiuos objektus tik tada kada naudoja. Aš siūlau susikurti Wrapper klasę patogiam darbui su ADO.NET. Dėl to, kad ši klasė dirba interfeisų lygyje, ji gali dirbti su bet kuriuo ADO.NET provider. Tokios klasės demo pavizdys yra pateiktas žemiau. 

Naudojant šią klasę jūsų kode bus pagrinde verslo logika, o ne darbo su ADO.NET objektais kodas, kuris padaro programos kodą daug sunkiau skaitomą. Taip pat radus klaidą darbo so ADO.NET objektais kode užteks pataisyti tik vienintelę šią klasę, o ne keisti kiekvieną programos vietą, kur buvo copy-pastinama ADO.NET objektų inicializacija..

Štai čia tokios klasės pavizdys:

using System;
using System.Data;
using System.Diagnostics;

/// <summary>
///
/// (C) Copyright 2009 Lythum.lt
/// Code written by Arvydas Grigonis
///
/// P.S.
///
/// Šis kodas nėra testuotas ir gali turėti klaidų
/// Čia tik demonstruojama pati koncepcija
///
/// </summary>
namespace Lythum.Samples.LT
{
	public class Sql
	{
		#region Attributes
		IDbConnection _Connection;		// ADO.NET connection
		IDbTransaction _Transaction;	// ADO.NET transaction
		String _LastSql;

		#endregion

		#region CTOR
		public Sql  (IDbConnection connection)
		{
			// jeigu connection null
			if(connection==null)
				throw new ArgumentNullException("connection");

			_Connection = connection;	// isimename connection
			_Transaction = null;	// nustatome tranzakcija kaip null
		}

		#endregion

		#region Connect
		/// <summary>
		/// Prisijungiame prie db su tranzakcijos valdymu
		/// </summary>
		/// <param name="beginTransaction"></param>
		/// <param name="commitLastTransaction"></param>
		/// <returns></returns>
		public bool Connect (
					bool beginTransaction,
					bool commitLastTransaction)
		{
			bool retVal = Connect ();

			// jeuigu prisijungta ir reikalinga tranzakcija
			if (retVal && beginTransaction)
			{
				// startuojame tranzakcija
				TransactionStart (commitLastTransaction);
			}

			return retVal;
		}

		/// <summary>
		/// Prisijungiame prie db
		/// </summary>
		/// <returns></returns>
		public bool Connect ()
		{
			try
			{
				// jungiames tik tuo atveju kada connection busena uzdaryta
				if (_Connection.State == ConnectionState.Closed)
				{
					_Connection.Open ();
				}

				return true;
			}
			catch (Exception ex)
			{
				// klaidu apdirbimas
				Error (ex);

				return false;
			}

		}

		public void Close ()
		{
			Close (true);
		}

		public void Close (bool commitLastTransaction)
		{
			TransactionStop (commitLastTransaction);

			Close ();
		}
		#endregion

		#region Commands
		/// <summary>
		/// Sis metodas sukuria komanda
		/// </summary>
		/// <returns></returns>
		public IDbCommand CreateCommand (bool connect)
		{
			IDbCommand cmd = null;

			try
			{
				// jeigu prisijungta sekmingai
				if (Connect ())
				{
					// sukuriame komanda
					cmd = _Connection.CreateCommand ();

					cmd.CommandType = CommandType.Text;

					// Jeigu egzistuoja aktyvi tranzakcija, priskiriame ja komandai
					if (_Transaction != null)
					{
						cmd.Transaction = _Transaction;
					}

				}

			}
			catch (Exception ex)
			{
				// Klaidu apdirbimas
				Error (ex);
			}

			return cmd;
		}
		#endregion

		#region Queries
		/// <summary>
		/// Query grazinanti DataTable rezultata
		/// Naudojama SELECT uzklausoms
		/// </summary>
		/// <param name="sql"></param>
		/// <param name="closeConnection"></param>
		/// <returns></returns>
		public DataTable Query (string sql, bool closeConnection)
		{
			Debug.Print ("Sql::Query: " + sql);
			if (string.IsNullOrEmpty (sql))
				throw new ArgumentException ("empty sql");

			Error ();	// pasaliname pries tai buvusias klaidas

			_LastSql = sql;	// isimename paskutini SQL debug poreikiams

			DataTable retVal = null;	// deklaruojame grazinama rezultata

			IDbCommand cmd = CreateCommand (true);	// sukuriame komanda

			if (cmd != null)
			{
				try
				{
					cmd.CommandText = sql;	// priskiriame sql uzklausa

					IDataReader reader = cmd.ExecuteReader ();	// vykdome reader

					retVal = new DataTable ("R");	// creating datatable
					retVal.Load (reader);	// uzpildome datatable query rezultatais
				}
				catch (Exception ex)
				{
					// klaidu apdirbimas
					Error (ex);
				}
				finally
				{
					cmd.Dispose ();	// atlaisviname command resursa

					// jeigu reikia uzdarome connection
					if (closeConnection && _Transaction == null)
					{
						Close ();
					}
				}
			}
			return retVal;
		}

		/// <summary>
		/// Skaliarine uzklausa, grazina pirmos eilutes, pirmo stulpelio reiksme
		/// naudinga uzklausoms:
		/// 
		/// SELECT COUNT(*) FROM somewhere
		/// </summary>
		/// <param name="sql"></param>
		/// <param name="closeConnection"></param>
		/// <returns></returns>
		public string QueryScalar (string sql, bool closeConnection)
		{
			// atliekame uzklausa
			DataTable table = Query (sql, closeConnection);

			// jeigu rezultatas egzistuoja, graziname ji
			if (table != null)
			{
				if (table.Rows.Count > 0 && table.Columns.Count > 0)
				{
					return table.Rows[0].ItemArray[0].ToString ();
				}

			}

			return string.Empty;
		}

		/// <summary>
		/// Execute tipo uzklausu metodas, naudojamas siu tipu SQL uzklausoms:
		/// 
		/// INSERT, DELETE, UPDATE
		/// </summary>
		/// <param name="sql"></param>
		/// <param name="closeConnection"></param>
		/// <returns></returns>
		public int Execute (string sql, bool closeConnection)
		{
			Debug.Print ("ExecSQL: " + sql);

			if (string.IsNullOrEmpty (sql))
				throw new ArgumentException ("empty sql");

			int retVal = -1;
			_LastSql = sql;

			IDbCommand cmd = CreateCommand (true);

			if (cmd != null)
			{
				try
				{
					cmd.CommandText = sql;
					retVal = cmd.ExecuteNonQuery ();
				}
				catch (Exception ex)
				{
					Error (ex);
				}
				finally
				{
					cmd.Dispose ();

					// close if set to close and if transaction not in progress
					if (closeConnection && _Transaction == null)
					{
						Close ();
					}
				}

			}

			return retVal;
		}


		#endregion

		#region Transactions

		public void TransactionStart (bool commitLastTransaction)
		{
			TransactionStop (commitLastTransaction);

			_Transaction = _Connection.BeginTransaction ();
		}

		public void TransactionStop (bool commitLastTransaction)
		{
			if (_Transaction != null)
			{
				if (commitLastTransaction)
				{
					_Transaction.Commit ();
				}
				else
				{
					_Transaction.Rollback ();
				}

				_Transaction.Dispose ();
				_Transaction = null;
			}
		}
		#endregion

		#region Errors

		/// <summary>
		/// Klaidu apdirbimas
		/// </summary>
		/// <param name="ex"></param>
		void Error (Exception ex)
		{
			Debug.Print (ex.Message);
		}

		/// <summary>
		/// Klaidos busenos pasalinimas
		/// </summary>
		void Error ()
		{
			Debug.Print ("Klaidos reset");
		}

		#endregion

	}
}

Žemiau pateikiamas naudojimo pavizdys:

// inicializuojame musu Sql klase su kokiu nors ADO.NET provider connection objektu
Sql sql = new Sql (new System.Data.SqlClient (ConnectionString));

// vykdome select uzklausa
DataTable table = sql.Query ("SELECT * FROM somewhere");

// vykdome insert uzklausa
sql.Execute ("INSERT INTO soemewhere ...");

// vykdome scalar uzklausa
String result = sql.QueryScalar ("SELECT COUNT(*) FROM somewhere");

// darbas su tranzakcijomis
sql.TransactionStart (true);	// pradedame tranzakcija
sql.Execute ("INSERT INTO soemewhere ...");
sql.Execute ("INSERT INTO soemewhere ...");
sql.TransactionStop (true);		// patvirtiname ir uzdarome tranzakcija

Darbas su ProgressBar

Paprastai dirbant su ProgressBar (System.Windows.Forms.ProgressBar) mes apdirbame kažkokį kiekį, kažkokių elementų. Tokiu atveju paprastai rašomas ciklas ir periodiškai ProgressBar valdymo elementui priskiriama nauja, einamoji progreso reikšmė. Vieną kartą šovė idėja kaip tai supaprastinti.

Visi ProgressBar elementai turi šiuos narius:

  1. int Minimum
  2. int Maximum
  3. int Value
Su jais galime rašyti tokį ciklą:
for (
      progressBar.Value = progressBar.Minimum = 0, progressBar.Maximum = 1000;
      progressBar.Value < progressBar.Maximum;
      progressBar.Value++)
    {
      DoSomething ();
    }

Tokiu atveju jokių papildomų kintamūjų nėra reikalinga.