Saturday, August 25, 2012

DataAccess in C#


While I was running through the ODP.NET samples on Connection I thought of implementing DbProviderFactory in a previous project I made.
This class has been made to use with different types of DataProviders.
A few datastores that are eligible:
  •         SQLServer
  •         Oracle
  •          MySql
  •          Access
  •          Excell
  •          XML
  •         ....
I use this class in all my projects from now on. Although it might contain some minor bugs still, I am pretty happy with it so far. I placed it on github where you can download the project.

Next post I will put this baby into action. 
I'll execute some code on the HR database shipped with a Oracle 11g R2 x64 Express install.
Most likely I ll make a video and post the code with it.

Enjoy!!

Class Diagram


IDataAccess Interface

using System.Data;
using System.Data.Common;
using System;
using System.Collections.Generic;

namespace DataAccess
{
    public interface IDataAccess : IDisposable
    {
        IDbConnection DbConnection { get; }

        string DataProvider { get; }

        DbProviderFactory DbProviderFactory { get; }
      
        bool CheckConnection();
       
        DataSet GetDataSet(IDbCommand command);
       
        DataTable GetDataTable(IDbCommand command);

        DataRow GetDataRow(IDbCommand command);

        int ExecuteNonQuery(IDbCommand command);

        void BeginTransaction();

        void BeginTransaction(IsolationLevel isolationLevel);

        void CommitTransaction();

        void RollBackTransaction();

        DataTable ExecuteStoredProcedure(string spName);

        DataTable ExecuteStoredProcedure(string spName, IList<DbParameter> inParameters,
                                                IList<DbParameter> outParameters, DbParameter returnValue);
    }
}
DataAccess class

using System;
using System.Data;
 using System.Transactions;
 using System.Collections.Generic;
using System.Data.Common;

namespace DataAccess
{
    public class DataAccess : IDataAccess
    {
        #region Variables
        /// <summary>
        /// Private readonly variable Connection of type IDbConnection. Holding all neccesary information about the connection.
        /// </summary>
        private readonly IDbConnection _connection;

        /// <summary>
        /// Private readonly variable DataProvider. Exposing information about the DataProvider.
        /// </summary>
        private readonly string _dataProvider;
        /// <summary>
        /// Private readonly variable Transaction of type IDbTransaction. holding information about the Transaction object.
        /// </summary>
        private IDbTransaction _transaction;

        private readonly DbProviderFactory _dbProviderFactory;
        #endregion

        #region Public Properties

        /// <summary>
        /// Public Property Connection of type IDbConnection. Holding all neccesary information about the connection.
        /// </summary>
        public IDbConnection DbConnection
        {
            get
            {
                return _connection;
            }
        }

        /// <summary>
        /// Name of the Data Provider
        /// </summary>
        public string DataProvider
        {
            get { return _dataProvider; }
        }

        /// <summary>
        /// DbProvider factory linked to the DataProvider
        /// </summary>
        public DbProviderFactory DbProviderFactory
        {
            get { return _dbProviderFactory; }
        }
        #endregion

        #region Constructors

        /// <summary>
        /// Overloaded Class Constructor.
        /// </summary>
        /// <param name="dataProvider">name of the dataprovider</param>
        /// <param name="connectionString">The connectionstring used for the dataprovider</param>
        public DataAccess(string dataProvider, string connectionString)
        {
            if (String.IsNullOrEmpty(connectionString))
                throw new ArgumentNullException("connectionString");
            if (String.IsNullOrEmpty(dataProvider))
                throw new ArgumentNullException("dataProvider");

            _dataProvider = dataProvider;

            //get the correct DbFactory providing the DB dataprovider
            _dbProviderFactory = DbProviderFactories.GetFactory(dataProvider);

            //Create a connection
            _connection = _dbProviderFactory.CreateConnection();

            //Set the connections connectionstring
            if (_connection != null)
                _connection.ConnectionString = connectionString;
        }

        #endregion

        #region Public Methods
        /// <summary>
        /// Check if you can make a connection with the database.
        /// </summary>
        /// <returns>Returns true if a connection is possible.</returns>
        public bool CheckConnection()
        {
            try
            {
                _connection.Open();
                _connection.Close();
                return true;
            }
            catch
            {
                return false;
            }
        }
        /// <summary>
        /// Generic method used to excecute a IDbCommand statement without parameters.
        /// </summary>
        /// <param name="command">Command statement of type IDbCommand</param>
        /// <returns>Returns the number of rows affected.</returns>
        public int ExecuteNonQuery(IDbCommand command)
        {
            int result;

            using (command)
            {
                _connection.Open();

                command.Connection = _connection;

                try
                {
                    //Using transactionscopes doesnt work too well on oracle databases.
                    using (TransactionScope scope = new TransactionScope())
                    {
                        result = command.ExecuteNonQuery();
                        scope.Complete();
                    }
                }
                finally
                {
                    _connection.Close();
                }
            }
            return result;
        }
        /// <summary>
        /// Start a transaction on the connection
        /// </summary>
        public void BeginTransaction()
        {
            if(_transaction == null)
                _transaction = DbConnection.BeginTransaction();
        }
        /// <summary>
        /// Begin a tracsaction on the connection by defining its isolationlevel
        /// </summary>
        /// <param name="isolationLevel"></param>
        public void BeginTransaction(System.Data.IsolationLevel isolationLevel)
        {
            if (_transaction == null)
                _transaction = DbConnection.BeginTransaction(isolationLevel);
        }
        /// <summary>
        /// Commit the transaction on the connection
        /// </summary>
        public void CommitTransaction()
        {
            if(_transaction != null)
            {
                _transaction.Commit();
                _transaction.Dispose();  
            }
        }
        /// <summary>
        /// Rollback transaction on the connection
        /// </summary>
        public void RollBackTransaction()
        {
            if(_transaction != null)
            {
                _transaction.Rollback();
                _transaction.Dispose();  
            }
        }

        #region Read Data
        /// <summary>
        /// Generic method that allows you to retrieve data from your datastore in a dataset.
        /// </summary>
        /// <param name="command">Command statement of type IDbCommand</param>
        /// <returns>A dataset with values as result of the command</returns>
        public DataSet GetDataSet(IDbCommand command)
        {
            DataSet ds = new DataSet();

            _connection.Open();

            using (command)
            {
                command.Connection = _connection;
                IDbDataAdapter da = _dbProviderFactory.CreateDataAdapter();
                if (da != null)
                {
                    da.SelectCommand = command;

                    try
                    {
                        da.Fill(ds);
                    }
                    finally
                    {
                        _connection.Close();
                    }
                }
            }

            return ds;
        }
        /// <summary>
        /// Generic method that allows you to retrieve data from your datastore in a datatable.
        /// </summary>
        /// <param name="command">Command statement of type IDbCommand</param>
        /// <returns></returns>
        public DataTable GetDataTable(IDbCommand command)
        {
            return GetDataSet(command).Tables[0];
        }
        /// <summary>
        /// Generic method that allows you to retrieve data from your datastore in a datarow.
        /// </summary>
        /// <param name="command">Command statement of type IDbCommand</param>
        /// <returns></returns>
        public DataRow GetDataRow(IDbCommand command)
        {
            DataRow dr = null;
            DataTable dt = GetDataTable(command);
            if (dt.Rows.Count > 0)
            {
                dr = dt.Rows[0];
            }
            return dr;
        }

        #endregion

        #region Implementing IDisposable
        /// <summary>
        /// Disposing our connection object.
        /// </summary>
        public void Dispose()
        {
            _connection.Dispose();
        }
        #endregion

        /// <summary>
        /// Public method to execute a stored procedure on the database.
        /// </summary>
        /// <param name="spName">Name of the stored procedure of the type string</param>
        /// <returns>A DataTable containing data returned by the stored procedure</returns>
        public DataTable ExecuteStoredProcedure(string spName)
        {
            return ExecuteStoredProcedure(spName, null, null, null);
        }
        /// <summary>
        ///  Public method to execute a stored procedure on the database providing parameters
        /// </summary>
        /// <param name="spName">Parameter of type String.Name of the stored procedure.</param>
        /// <param name="inParameters">List of In Parameters of type DbParameter</param>
        /// <param name="outParameters">List of Our Parameters of type DbParameter</param>
        /// <param name="returnValue"></param>
        /// <returns>Return a datatable with whatever returns from the database.</returns>
        public DataTable ExecuteStoredProcedure(string spName, IList<DbParameter> inParameters, IList<DbParameter> outParameters, DbParameter returnValue)
        {
            var command = _dbProviderFactory.CreateCommand();
            if (command != null)
            {
                _connection.Open();

                command.Connection = (DbConnection)DbConnection;
                command.CommandType = CommandType.StoredProcedure;
                command.CommandText = spName;

                if (returnValue != null)
                {
                    returnValue.Direction = ParameterDirection.ReturnValue;
                    command.Parameters.Add(returnValue);
                }

                if (inParameters != null)
                {
                    foreach (var parameter in inParameters)
                    {
                        parameter.Direction = ParameterDirection.Input;
                        command.Parameters.Add(parameter);
                    }
                }

                if (outParameters != null)
                {
                    foreach (var parameter in outParameters)
                    {
                        parameter.Direction = ParameterDirection.Output;
                        command.Parameters.Add(parameter);
                    }
                }
            }


            //Does returning this datatable actually work every time?

            DataTable dataTable = null;

            try
            {
                if (command != null)
                {
                    using (IDataReader dataReader = command.ExecuteReader())
                    {
                        dataTable = new DataTable();
                        dataTable.Load(dataReader);
                    }
                }
            }
            finally
            {
                _connection.Close();
            }

            return dataTable;
        }
        #endregion

        #region Public Static Methods
        // This example assumes a reference to System.Data.Common.
        public static DataTable GetProviderFactoryClasses()
        {
            // Retrieve the installed providers and factories.
            return DbProviderFactories.GetFactoryClasses();
        }
        #endregion
    }
}

Saturday, July 14, 2012

A new desktop installation

The current project at work is running on a 64x W7 OS environment. As mine at home was a 86x it was time to reinstall everything.

That's what I installed this week.

Office 2007
Office Viso
Office Project

League Of Legends (This game is important to blow off some steam!! And above all, free to play)


SQLDeveloper => reference your JDK java.exe in the bin folder. Ignore 7.1 higher version warning.

Autocad 2013 x64
Autocad Map3D x64 + Infrastructure Administrator

Deamon Tools Lite (to get those iso files up and running)

Resharper5.1 (MSVS code resharper)



Now lets hope I don't have to do this again soon...

Sunday, May 20, 2012

MSVS TFS Practical Ruck Guidance

Today I dug a little deeper in some white papers and guidance the ALM rangers are sharing on CodePlex.

One of the topics they cover is the use of the RUCK software development technique.

While I have seen Agile and Scrum so far, I was really interested in this one. Why?

Atm, I am working in a team where this kind of approach might be a lot better then the Agile or Scrum development techniques.
You can find more in detail here.
Because I was so impressed I shared the explanation on RUCK, which in the rugby world means "loose scrum", on YouTube to give you a quick intro on the idea behind the technique.

This video & documentation should give you an idea if this technique might be applicable in your working environment.


Saturday, May 19, 2012

Application Lifecycle Management & Team Foundation Server


Version Control & ALM
As GIS developer I use Team Foundation Server on a daily basis now. 

I used Subversion in the past, but TFS is fairly new to me. 
I've been using both products as version control only and was really interested to figure out how this tool (TFS) can be used as ALM. 
A colleague of mine suggested the use of TFS as ALM this week during a meeting.

Because of that, I decided to quickly figure out the do's and don'ts and get myself up to speed with the product and it's features.

ALM & TFS VIDEOS
Today I followed a 4 hour video course on ALM and TFS. A complete summary of the topics I tackled can be found here.

IRL Application
The video's cover a series of topics that could resolve some difficulties we face at work. I am very interested how this unfolds.

Because I don't have TFS installed at home I will have to wait till Monday to test some features I can quickly implement for personal purposes.

My First Oracle Setup


I have experience with SQL server but I am very new to Oracle Database technologies. So, it was time for me to touch the basics and take a look at some basic features Oracle holds in store for us.

1.Download
First I downloaded and installed the latest version of the oracle database available at http://www.oracle.com/technetwork/database/enterprise-edition/downloads/index.html
Make sure you remember your password after installation!!

2.Helpfull documentation
I got myself all the necessary documentation at http://docs.oracle.com/cd/E17781_01/index.htm and started with the getting started pdf.

3.Install SQL Developer
As I am not a huge fan of using the command line to configure the database, I installed the SQL developer which allows you to do the same but in a graphical environment. I downloaded it at http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html
To use the database tool, make sure you have the latest Java JDK installed on your computer. You can download it here http://www.oracle.com/technetwork/java/javase/downloads/index.html

4.Database Home Page (pdf ref 1.2)
For me this can be found at C:\oraclexe\app\oracle\product\11.2.0\server\Get_Started. Launch it and it will open in your web browser and give you access to various database administration operations.

5.Create a new User (pdf ref 2.0)
That’s why I installed the SQL developer, to make these things a lot easier then typing inside an old prompt window.
First you have to start by creating a SYSTEM connection. The username should be SYSTEM and password is the one you defined on Oracle Database installation. The name of the connection can be chosen freely.


If all went well you should see a tree view with a lot off tree nodes. Most of them are Chinese still, but there are similarities to SQL server. The treenode Other Users is the one where we define a new user and set up its privileges.



6.UNLOCK HR SAMPLE DATA
There is a HR user inside the Other Users section that should have his account unlocked. This grants you access to the tables tied to that user profile. Modify the properties of that user using the SYSTEM connection and define a new password for that HR user.
The pdf Getting Started guide continued with building an application using the wizard on the Getting Started page but I’ll skip that one. If you are into wizards, feel free to run this sample :)


7.Oracle Database XE

I read the second pfd in line found at http://docs.oracle.com/cd/E17781_01/index.htm and filtered some of the most important things I need to communicate in a descent manner from a .Net environment. At least I have a good first general impression of the Oracle Database XE now and this should be more than enough to get me started.

In the next post I’ll try to connect to the database and pull data from the HR tables using C#.

Thursday, May 10, 2012

Design Patterns - Singleton Pattern

Definition
Ensures a class has only one instance, and provides a global access to it.

Pattern examples
There are a few different approaches on how to implement the singleton pattern. I’ll show some in a C# environment.

Example 1 : “Lazy loading”.
By implementing lazy loading you insure that your class only gets instantiated when it is called upon for the first time and not earlier.

C# Code
/// <summary>
/// Singleton class. Lazy Loading. Instantiation only happens when the class is called upon for the first time.
/// Pitfall : Multithreading might result in ending up with 2 instances of the class. This implementation is not thread safe!

    /// </summary>
    public class MyLazySingleton
    {
        private static MyLazySingleton instance;

        /// <summary>
        /// Public static method that returns an instance of MyLazzySingleton
        /// </summary>
        /// <returns>Unique Instance of MyLazySingleton</returns>
        public static MyLazySingleton Instance()
        {
            //instantiate a new instance of the class if it is null
            if (instance == null)
                instance = new MyLazySingleton();
            return instance;
        }
    }

Pitfall
This piece of code is not ideal in a multithreading environment. Two instances can still be instantiated at the same time if both separate threads run over this code check:
//instantiate a new instance of the class if it is null
            if (instance == null)

Meaning, for both threads this check will be true and they will both instantiate an instance of that class, which is exactly what we want to prevent using the singleton pattern. Outside a multithreading environment this code works just fine. 

Example 2 : “Eagerly Creation”.

If the load is done at the start of the application or you are sure the class will get used for sure within your application, use eagerly creation of your singleton class. This is a thread safe implementation.

C# Code
/// <summary>
/// Singleton class. Eagerly Creation. Use this type of singleton if the load is done on startup or you are sure the singleton will be used
    /// at least once in your program. This implementation is thread safe!
    /// </summary>
    class MyEagerSingleton
    {
        /// <summary>
        /// Declare and instantiate immediatly
        /// </summary>
        private static MyLazySingleton instance = new MyLazySingleton();

        /// <summary>
        /// Public static method that returns an instance of MyEagerSingleton
        /// </summary>
        /// <returns>Unique Instance of MyEagerSingleton</returns>
        public static MyLazySingleton Instance()
        {
            return instance;
        }