Hvordan forenkle database koding

Når man lager applikasjoner eller websider som kommuniserer med databaser koder man mange funksjoner som gjør nesten det samme. Forskjellen er som regel bare hvilke parametre som skal sendes til databasen og hva som er navnet på prosedyren i SQL (eller selve SQL-setningen). Med en enkel klasse kan man forenkle dette betraktielig for å gjøre hverdagen litt enklere.

Løsningen på dette kan være å lage en abstrakt klasse som du arver fra de gangene du skal gjøre ting i databasen. Klassen gir deg tilgang til funksjoner og metoder som gjør at dette blir veldig enkelt. I dette eksempelet er det laget en abstrakt klasse som kalles DataAccessBase og denne klassen inneholder følgende funksjoner:

  • ExcecuteDataReader(string commandText)
  • ExcecuteNonQuery(string commandText)
  • ExcecuteScalar(string commandText)
  • ExcecuteDataTable(string commandText, string tableName)
  • AddParameter(string parameterName, object value, SqlDbType sqlDbType, int size)
  • AddParameter(string parameterName, object value, SqlDbType sqlDbType, int size, ParameterDirection direction)
  • GetParameter(string parameterName)
  • Dispose()

I konstruktøren til klassen opprettes det objekter for SqlConnectionSqlCommand og SqlDataReader som du har tilgang til når du arver.

Følgende kode gir det et eksempel på hvor mye enklere ting kan gjøres med denne metode. Eksempelet viser hvordan man gjør det vanligvis og nederst finner du hvordan det gjøre med klassen DataAccessBase

public class NormalDataAccess
{
    // Et enkelt eksempel på en metode som lagrer en bruker.
    // Eksempelet viser en Stored Procedure som returnerer UserId etter lagring
    public int AddUser(string username, string password)
    {
        SqlConnection conn = new SqlConnection("connectionString");
        SqlCommand cmd = new SqlCommand("spMyProcedure", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@UserId", DBNull.Value));
        cmd.Parameters["@UserId"].SqlDbType = SqlDbType.Int;
        cmd.Parameters["@UserId"].Size = 4;
        cmd.Parameters["@UserId"].Direction = ParameterDirection.Output;
        cmd.Parameters.Add(new SqlParameter("@Username", username));
        cmd.Parameters.Add(new SqlParameter("@Password", password));

        conn.Open();
        cmd.ExecuteNonQuery();
        conn.Close();

        int userId = Convert.ToInt32(cmd.Parameters["@UserId"].Value);

        cmd.Dispose();
        conn.Dispose();

        return userId;
    }

    // Enkelt eksempel som bare kjører en sql-kommando
    public void ExecuteSqlCommand()
    {
        SqlConnection conn = new SqlConnection("connectionString");
        SqlCommand cmd = new SqlCommand("spMyProcedure", conn);
        cmd.CommandType = CommandType.StoredProcedure;
        conn.Open();
        cmd.ExecuteNonQuery();
        conn.Close();
        cmd.Dispose();
        conn.Dispose();
    }
}



// Samme to eksempler som over, men med DataAccessBase
public class SimplifiedDataAccess : DataAccessBase
{
    public int AddUser(string username, string password)
    {
        base.AddParameter("@UserId", DBNull.Value, SqlDbType.Int, 4, ParameterDirection.Output);
        base.AddParameter("@Username", username, SqlDbType.VarChar, 255);
        base.AddParameter("@Password", password, SqlDbType.VarChar, 255);
        base.ExecuteNonQuery("spUsers_AddUser");
        int UserId = Convert.ToInt32(base.GetParameter("@UserId").Value);
        base.Dispose();
        return UserId;
    }

    public void ExecuteSqlCommand()
    {
        base.ExecuteNonQuery("spMyProcedure");
        base.Dispose();
    }
}

Det eneste du trenger er selve klassen. Den ser du her. Den er ganske selvforklarende så jeg skriver ikke noe mer rundt dette. (se eksempelet som kan lastes ned nederst i artikkelen)

    public abstract class DataAccessBase
    {
        public SqlConnection Connection;
        public SqlCommand Command;
        public SqlDataReader DataReader;

        public DataAccessBase()
        {
            Connection = new SqlConnection("### Your connectionstring ###");
            Command = new SqlCommand("", Connection);
            Command.CommandType = CommandType.StoredProcedure;
        }

        public void Dispose()
        {
            if ((DataReader != null) && (!DataReader.IsClosed))
                DataReader.Close();

            if (Connection.State == ConnectionState.Open)
                Connection.Close();

            DataReader = null;
            Command.Dispose();
            Command = null;
            Connection.Dispose();
            Connection = null;
        }

        public void ExecuteDataReader(string commandText)
        {
            if (Connection.State == ConnectionState.Closed)
                Connection.Open();

            this.Command.CommandText = commandText;
            this.DataReader = this.Command.ExecuteReader();
        }

        public void ExecuteNonQuery(string commandText)
        {
            Command.CommandText = commandText;

            if (Connection.State == ConnectionState.Open)
            {
                Command.ExecuteNonQuery();
            }
            else
            {
                Connection.Open();
                Command.ExecuteNonQuery();
                Connection.Close();
            }
        }

        public object ExecuteScalar(string commandText)
        {
            Command.CommandText = commandText;
            object value = null;

            if (Connection.State == ConnectionState.Open)
            {
                value = Command.ExecuteScalar();
            }
            else
            {
                Connection.Open();
                value = Command.ExecuteScalar();
                Connection.Close();
            }

            return value;
        }

        public DataTable ExecuteDataTable(string commandText, string tableName)
        {
            Command.CommandText = commandText;
            DataTable dt = null;

            if (Connection.State == ConnectionState.Open)
            {
                SqlDataAdapter da = new SqlDataAdapter(Command);
                dt = new DataTable(tableName);
                da.Fill(dt);
            }
            else
            {
                Connection.Open();
                SqlDataAdapter da = new SqlDataAdapter(Command);
                dt = new DataTable(tableName);
                da.Fill(dt);
                Connection.Close();
            }

            return dt;
        }

        public void AddParameter(string parameterName, object value, SqlDbType sqlDbType, int size)
        {
            AddParameter(parameterName, value, sqlDbType, size, ParameterDirection.Input);
        }

        public void AddParameter(string parameterName, object value, SqlDbType sqlDbType, int size, ParameterDirection direction)
        {
            SqlParameter p = new SqlParameter(parameterName, value);
            p.SqlDbType = sqlDbType;
            p.Size = size;
            p.Direction = direction;
            Command.Parameters.Add(p);
        }

        public SqlParameter GetParameter(string parameterName)
        {
            return this.Command.Parameters[parameterName];
        }
    }

Last ned eksempelkode her: SimplifyDataAccess.zip (5 kb)