Go Back   CodeCall Programming Forum > Software Development > Tutorials > CSharp Tutorials
Register Blogs Search Today's Posts Mark Forums Read

CSharp Tutorials Tutorials for C#

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
  #1 (permalink)  
Old 09-01-2009, 03:42 PM
ArekBulski's Avatar
Guru
 
Join Date: Mar 2009
Posts: 1,373
ArekBulski is just really niceArekBulski is just really niceArekBulski is just really niceArekBulski is just really niceArekBulski is just really nice
Arrow Writing SQL commands in C# - Part 3 - Editing records and maintainable code

Welcome all! My previous two turorials about inserting, reading and deleting records were so welcomed that I decided to write another one. If you have read them then let's assume we already have a solution with a database attached. We also got few records in a table.

Today however, I will focus on something more important than working code. I want you to see how awesome prototypes and dedicated classes are. First one will give us immediate feedback about how good the code is, second one will be a very well designed code that can be maintained over ages.

Editing existing records: using SQL UPDATE statement

Here is a piece of code that executes yet another SQL statment. It will modify as many records as you want, only the conditions you specify will make which records are changed. Warning: If you don't specify that WHERE clause then it will eat all your data in the table. I would rather not want to make a mistake like this and mess up my company database.

I just copied this code from the code above, and modified one line. I strongly believe that it is a very good way to make a prototype and immediately know does it work or not. That is what a prototype is for.

Code:
SqlConnection connection1 = new SqlConnection(
    Properties.Settings.Default.some_numbersConnectionString);

SqlCommand insertCommand = new SqlCommand(
    "UPDATE NumbersTable SET number = 1003, description = 'changed my mind' WHERE number = 1002",
    connection1);

connection1.Open();
insertCommand.ExecuteNonQuery();
connection1.Close();

MessageBox.Show("Records 1002s have been changed to 1003s. Please check your table data again. :)");


Structure your code: dedicated class for database operations

As you see here, most of SQL operations are very schematic (even reading). They are copied again and again and I just change one line that carries the SQL statment. Look at the full code and think about is this something you would like show to your employers. My honest opinion is that this code is too redundant. Every method alone works great. But making a new connection for every query seems wrong.

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void InsertButton_Click(object sender, EventArgs e)
        {
            SqlConnection connection1 = new SqlConnection(
                Properties.Settings.Default.some_numbersConnectionString);

            SqlCommand insertCommand = new SqlCommand(
                "INSERT into NumbersTable values (1002, 'will delete this one')",
                connection1);

            connection1.Open();
            insertCommand.ExecuteNonQuery();
            connection1.Close();

            MessageBox.Show("Record 1002 inserted. Please check your table data. :)");
        }

        private void ReadButton_Click(object sender, EventArgs e)
        {
            SqlConnection connection1 = new SqlConnection(
                Properties.Settings.Default.some_numbersConnectionString);
            SqlCommand selectCommand = new SqlCommand(
                "SELECT * FROM NumbersTable",
                connection1);

            connection1.Open();
            SqlDataReader reader = selectCommand.ExecuteReader();
            string fetchedRecords = string.Empty;

            while (reader.Read() == true)
            {
                fetchedRecords += "Record: (number) " + reader[0] + " (descriptio) " + reader[1] + " \n";
            }

            connection1.Close();
            MessageBox.Show("Found following records: \n \n" + fetchedRecords);
        }

        private void DeleteButton_Click(object sender, EventArgs e)
        {
            SqlConnection connection1 = new SqlConnection(
                Properties.Settings.Default.some_numbersConnectionString);

            SqlCommand insertCommand = new SqlCommand(
                "DELETE NumbersTable WHERE number = 1002",
                connection1);

            connection1.Open();
            insertCommand.ExecuteNonQuery();
            connection1.Close();

            MessageBox.Show("Records 1002s deleted. Please check your table data again. :)");
        }

        private void EditButton_Click(object sender, EventArgs e)
        {
            SqlConnection connection1 = new SqlConnection(
                Properties.Settings.Default.some_numbersConnectionString);

            SqlCommand insertCommand = new SqlCommand(
                "UPDATE NumbersTable SET number = 1003, description = 'changed my mind' WHERE number = 1002",
                connection1);

            connection1.Open();
            insertCommand.ExecuteNonQuery();
            connection1.Close();

            MessageBox.Show("Records 1002s have been changed to 1003s. Please check your table data again. :)");

        }

    }
}
Now the suprising part. I really think this way of coding is very *good*. You might ask "is this a good practice? this is crap". And I would agree. This code is a prototype. Making it took me less time (also because I copied and copied) so it saved me time on designing something that I would change later anyway. It also gave me a real insight into how my code should look like.

What I would like to do now, is put all our database operations into a dedicated class. We already have a *working* prototype, shall we make a second *maintainable* solution?



Code:
private void button1_Click(object sender, EventArgs e)
        {
            string message = "Here are logs for all operations made: \n";

            message += "Adding a 1002 record twice. \n";
            DatabaseOperations.ExecuteSqlStatement("INSERT into NumbersTable values (1002, 'will delete this one')");
            DatabaseOperations.ExecuteSqlStatement("INSERT into NumbersTable values (1002, 'will delete this one')");


            message += "Reading all records present: \n";
            SqlDataReader reader = DatabaseOperations.ExecuteSqlReader("SELECT * FROM NumbersTable");
            while (reader.Read() == true)
                message += "  Record: (number) " + reader[0] + " (description) " + reader[1] + " \n";
            reader.Close();


            message += "Editing all 1002 records into 1003s. \n";
            DatabaseOperations.ExecuteSqlStatement("UPDATE NumbersTable SET number = 1003, description = 'changed my mind' WHERE number = 1002");


            message += "Reading all records present (again): \n";
            reader = DatabaseOperations.ExecuteSqlReader("SELECT * FROM NumbersTable");
            while (reader.Read() == true)
                message += "  Record: (number) " + reader[0] + " (description) " + reader[1] + " \n";
            reader.Close();


            MessageBox.Show(message);
        }
Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace WindowsFormsApplication1
{
    /// <summary>
    /// This class performs the database operations. Pass on SQL statements and 
    /// it will just return the data for you. 
    /// </summary>
    public static class DatabaseOperations
    {
        /// <summary>
        /// This connection will do everything. Better to not throw connections 
        /// on left and right.
        /// </summary>
        private static SqlConnection connectionForAllOperations;

        /// <summary>
        /// This method executes any non-reader command. Use it for INSERT, UPDATE 
        /// and DELETE. It does not work for SELECT, sorry.
        /// </summary>
        public static void ExecuteSqlStatement(string sql)
        {
            if (connectionForAllOperations == null)
            {
                /// The connection will be opened only once, just before first operation.
                connectionForAllOperations = new SqlConnection(
                    Properties.Settings.Default.some_numbersConnectionString);
                connectionForAllOperations.Open();
            }

            SqlCommand anyCommand = new SqlCommand(sql, connectionForAllOperations);
            anyCommand.ExecuteNonQuery();
        }

        /// <summary>
        /// This method executes a reader command. Use for SELECT queries. 
        /// </summary>
        public static SqlDataReader ExecuteSqlReader(string sql)
        {
            if (connectionForAllOperations == null)
            {
                /// The connection will be opened only once, just before first operation.
                connectionForAllOperations = new SqlConnection(
                    Properties.Settings.Default.some_numbersConnectionString);
                connectionForAllOperations.Open();
            }

            SqlCommand anyCommand = new SqlCommand(sql, connectionForAllOperations);
            SqlDataReader anyReader = anyCommand.ExecuteReader();
            return anyReader;
        }

    }
}
I would like to take an opportunity to make a breaking point in the way coding is conducted. I think every manager would say that I should skip the first crap and proceed to working on the solution, probably to save time. I would totally disagree here. Here are my arguments.

I made a prototype really quickly, almost in no time. That is because I could do as I want and no code quality was needed. I also made the solution really quickly. You might not believe me but I copied most of the stuff and just renamed and refactored it. At the same time...

Class design is completely new. I eliminated the big flaws that were existing in the prototype. Therefore the solution is very maintainable. And that is worth some employees time, sweat and earnings in the future.

Also building a prototype gave me a real insight into how SQL queries work. That knowledge is very important when building a solution (first or not), as much as when solving bugs. It will also pay off when implementing all the details that a solution would require.

The manager could say: "Then design the software well in the beginning". Of course it sounds like a great idea. But how will I design something I never saw on my own eyes so far? I am pretty sure that the folks at NASA really took their time to design their first space rockets, those ones with higher oxygen level inside. They had the design, but not experience. Let the astronauts rest in peace.
Attached Thumbnails
writing-sql-commands-c-part-3-editing-records-maintainable-dedicated-clas-operations-logs.jpg   writing-sql-commands-c-part-3-editing-records-maintainable-dedicated-clas-reading-records.jpg  
Attached Files
File Type: zip SqlCommand example, version 03, editing records.zip (58.5 KB, 52 views)
File Type: zip SqlCommand example, version 04, dedicated class.zip (58.2 KB, 49 views)
File Type: zip some_numbers database.zip (166.2 KB, 60 views)

Last edited by ArekBulski; 09-02-2009 at 10:16 AM..
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #2 (permalink)  
Old 09-02-2009, 08:06 AM
Jordan's Avatar
Administrator
 
Join Date: Nov 2005
Location: Hendersonville, NC
Posts: 24,556
Jordan is a name known to allJordan is a name known to allJordan is a name known to allJordan is a name known to allJordan is a name known to allJordan is a name known to all
Send a message via ICQ to Jordan Send a message via AIM to Jordan Send a message via MSN to Jordan Send a message via Yahoo to Jordan
Re: Writing SQL commands in C# - Part 3 - Editing records and maintainable dedicated

Very nice! That first image is broken for me. +rep
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 09-02-2009, 05:08 PM
WingedPanther's Avatar
Super Moderator
 
Join Date: Jul 2006
Age: 36
Posts: 11,435
WingedPanther has much to be proud ofWingedPanther has much to be proud ofWingedPanther has much to be proud ofWingedPanther has much to be proud ofWingedPanther has much to be proud ofWingedPanther has much to be proud ofWingedPanther has much to be proud ofWingedPanther has much to be proud ofWingedPanther has much to be proud of
Re: Writing SQL commands in C# - Part 3 - Editing records and maintainable dedicated

Nice job +rep
__________________
CodeCall Blog | CodeCall Wiki | Shareware
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
Reply



Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes



All times are GMT -5. The time now is 10:28 AM.


vBulletin v3.8.0 ©2010, Jelsoft Enterprises Ltd.


no new posts

LinkBacks Enabled by vBSEO 3.1.0