How do I access a MySQL database with C#?

This was a little bit easier for me because I had just figured all this out on Microsoft SQL and (lo and behold), MySQL had created the exact same function structure for MySQL.

So I read through this document first:
Beginning MYSQL 5 with Visual Studio.NET 2005.pdf

It was very informative and showed this code to get into a MySQL database:

string connectionString = "server=ServerName; user id=UserName; password=P@sswd!; database=MyDatabase";
string query = "Select * from users";
MySqlConnection connection = new MySqlConnection(connectionString);
try
{
    connection.Open();
    MySqlDataAdapter dataAdapter = new MySqlDataAdapter(query, connection);
    DataSet dataSet = new DataSet();
    dataAdapter.Fill(dataSet, "users");
}

I had been accessing tables in a Microsoft SQL database using a different set of functions, so I tested to see if the method I had been using for Microsoft SQL would work for MySQL, since the object and function names are almost identical.

The following code also accessed the database and I like it better because a DataTable seems more of an obvious choice to return data from table.

string connectionString = "server=ServerName; user id=UserName; password=P@sswd!; database=MyDatabase";
string query = "Select * from users";
MySqlConnection connection = new MySqlConnection(connectionString);
try
{
    connection.Open();
    MySqlCommand command = new MySqlCommand(query, connection);
    MySqlDataReader reader = command.ExecuteReader();;
    DataTable table = new DataTable();
    table.Load(reader);
}

So I left wondering how these two methods are different…I guess I need to answer the following:

  1. Which of the above two SQL database access methods should be considered best practice and why?
  2. Is one more efficient than the other?
  3. What is the difference between a DataSet and a DataTable?
    DataSet Class
    DataTable Class

Why my variable and object names in my code are so long

WhyMyVariableAndObjectNamesInMyCodeAreSoLong

Reason 1 – One of the main reasons that variable names have been shortened in the past are because you have to type them and the longer they are the longer they take to type. However, with today’s Integrated Development Environments (IDEs) you only have to type a few characters and then hit tab or enter and it finishes the variables for you. So this reason for short variable names has become a non-factor.

Reason 2 – The longer the variable name, the better documented your code is. Lets face it, there are those that demand documentation and those that argue that code should be so well written it doesn’t need documentation. So if I have a variable that represents the time it takes to drive to work, I will go ahead and make the variable name, theTimeItTakesToDriveToWork.


The Tower of Hanoi as an example of using a recursive functions in C++

I am not going to explain the Tower of Hanoi here. I assume if you are reading this you know what you are looking for. Otherwise, read this:
http://en.wikipedia.org/wiki/Tower_of_Hanoi

Main.cpp

#include <iostream>
#include "TowerOfHanoi.h"

int main()
{
	TowerOfHanoi *toh = new TowerOfHanoi(true);
	std::cout << toh->toString();
	toh->solve();
	system("pause");
}

TowerOfHanoi.h

#include <iostream>
#include <string>
#include <sstream>
#include <string>

#define leftPeg 1
#define middlePeg 2
#define rightPeg 3

class TowerOfHanoi
{
	public:
		// Constructors
		TowerOfHanoi(bool inPromptUser);
		TowerOfHanoi(int inNumberOfRings);

		// Destructor
		~TowerOfHanoi();

		// Other functions
		void solve();

		// Standard functions
		std::string toString();
		bool equals(TowerOfHanoi inTowerOfHanoi);

	private:
		void initializeClass(int inNumberOfRings);
		void runRecursiveAlgorithm(int inNumberOfRings, int mPegOriginallyHoldingRing, int inTemporaryPeg, int inDestinationPeg);
		std::string intToString(int i);
		int power(int inInteger, int inExponent);
		std::string getTabs();

		int mNumberOfRings;
		int mPegOriginallyHoldingRing;
		int mDestinationPeg;
		int mTemporyPeg;
		int mNumberOfStepsToSolve;
		int mStepCounter;
};

TowerOfHanoi.cpp

#include "TowerOfHanoi.h"
#include <iostream>
#include <string>
// Constructors
TowerOfHanoi::TowerOfHanoi(bool inPromptUser)
{
	int tmpNumberOfRings;
	std::cout << std::endl << "How many rings? &#91;1 - 10&#93; " << std::endl;
	std::cin >> tmpNumberOfRings;
	initializeClass(tmpNumberOfRings);
}

TowerOfHanoi::TowerOfHanoi(int inNumberOfRings)
{
	initializeClass(inNumberOfRings);
}

// Destructor
TowerOfHanoi::~TowerOfHanoi()
{
}

// Other functions
void TowerOfHanoi::solve()
{
	mStepCounter = 0;
	runRecursiveAlgorithm(mNumberOfRings, mPegOriginallyHoldingRing, mTemporyPeg, mDestinationPeg);
}

// Private functions
void TowerOfHanoi::initializeClass(int inNumberOfRings)
{
	mNumberOfRings = inNumberOfRings;

	mNumberOfStepsToSolve = power(2, inNumberOfRings) - 1;

	mPegOriginallyHoldingRing = leftPeg;
	mDestinationPeg = rightPeg;
	mTemporyPeg = middlePeg;
	mStepCounter = 0;
}

void TowerOfHanoi::runRecursiveAlgorithm(int inNumberOfRings, int mPegOriginallyHoldingRing, int inTemporaryPeg, int inDestinationPeg)
{
	std::string tabs = "\t\t";
	if (inNumberOfRings == 1)
	{
		std::cout << "Step " << ++mStepCounter << getTabs() << mPegOriginallyHoldingRing << " > " << inDestinationPeg << std::endl;
	}
	else
	{
		runRecursiveAlgorithm(inNumberOfRings - 1, mPegOriginallyHoldingRing, inDestinationPeg, inTemporaryPeg);
		std::cout << "Step " << ++mStepCounter << getTabs() << mPegOriginallyHoldingRing << " > " << inDestinationPeg << std::endl;
		runRecursiveAlgorithm(inNumberOfRings - 1, inTemporaryPeg, mPegOriginallyHoldingRing, inDestinationPeg);
	}
}

std::string TowerOfHanoi::getTabs()
{
	if (mStepCounter > 99)
	{
		return "\t";
	}
	return "\t\t";
}

// Standard functions
std::string TowerOfHanoi::intToString(int i)
{
	std::stringstream ss;
	std::string s;
	ss << i;
	s = ss.str();
	return s;
}

int TowerOfHanoi::power(int inInteger, int inExponent)
{
	int retVal = 1;
	for (int i = 0; i < inExponent; i++)
	{
		retVal *= inInteger;
	}

	return retVal;
}

// Standard Functions
std::string TowerOfHanoi::toString()
{
	return "Tower of Hanoi with " + intToString(mNumberOfRings) + " rings.\n";
}

bool TowerOfHanoi::equals(TowerOfHanoi inTowerOfHanoi)
{
	if (this->mNumberOfRings == inTowerOfHanoi.mNumberOfRings)
	{
		return true;
	}
	return false;
}

Understanding the Unary Scope Resolution Operator

The Unary Scope Resolution Operator is used to access a global variable when a local variable of the same name exists.

For example, look at the following code

#include
using namespace std;

int number = 100;

int main()
{
double number = 27.9;

int a = number;
// The global variable ::number is intended.
// This line should be: int a = ::number;
cout << a; cout << number; cout << ::number; } [/sourcecode] Question
What is the value of A going to be? 27.9 or 100?
Answer
Neither, it will be 27.

Explanation
One can assume that because variable a is an int and the global variable number is an int, that the global variable ::number was intended over the local variable number.

However, the local variable number that is a double was used.

Since variable a is an int, the value of the local variable number is casted to an int when assigned, so 27.9 becomes 27.

This can lead to difficult to solve bugs. The value should be 100 but is 27.

Looking at the code, this doesn’t look obviously wrong.

If a developer makes it a practice to always preface global variables with the Unary Scope Resolution Operator, such bugs can be avoided.


How do I get the number of rows returned from a Microsoft SQL Query in C#?

How do I get the number of rows returned from a SQL Query in C#?

Having used other languages where this is much simpler, I was surprised at how “not simple” this was in C#. I expected it to be a little more complex than in some scripting language such as PHP, but it was way more complex.

Here is how I do it:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace CountRows
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a string to hold the database connection string
            string sdwConnectionString = @"Data Source = ServerName; user id=UserName; password=P@sswd!; Initial Catalog = DatabaseName;";

            // Create a string to hold the database connection string
            string query = "SELECT * FROM MyTable";

            // Pass both strings to a new SqlCommand object.
            SqlCommand queryCommand = new SqlCommand(query, sdwDBConnection);

            // Create a SqlDataReader
            SqlDataReader queryCommandReader = queryCommand.ExecuteReader();

            // Create a DataTable object to hold all the data returned by the query.
            DataTable dataTable = new DataTable();
            dataTable.Load(queryCommandReader);

            // The DataTable object has a nice DataTable.Rows.Count property that returns the row count.
            int rowCount = rowCount = dataTable.Rows.Count;
        }
    }
}

Now doing it this way, you also have the data available in the DataTable dataTable object so you don’t have to go to the database and get it again.

 

Return to ADO.NET and Database with C#


How I get the number of a rows in a Micorosft SQL table using C#?

How I get the number of rows in a table using C#?

Here is a step by step:

Step 1 – Create a new class: (attached click here: SQLTableRowCounter.cs)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace SQLTableRowCounter
{
    class SQLTableRowCounter
    {
        private string mCountQuery;
        private SqlConnection mConnection;
        private int mNumberOfRows;

        public SQLTableRowCounter(String inTableName, SqlConnection inConnection)
        {
            mCountQuery = "SELECT COUNT(*) FROM " + inTableName;
            mConnection = inConnection;
            mConnection.Open();
            SqlCommand mCountQueryCommand = new SqlCommand(mCountQuery, mConnection);
            mNumberOfRows = (int)mCountQueryCommand.ExecuteScalar();
        }

        public int NumberOfRows
        {
            get { return mNumberOfRows; }
            set { mNumberOfRows = value; }
        }
    }
}

Step 2 – Now create the object and get the value:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;

namespace SQLTableRowCounter
{
    class Program
    {
        static void Main(string[] args)
        {
             string connectionString = @"Data Source = ServerName; user id=UserName; password=P@sswd!; Initial Catalog = DatabaseName;";
             SqlConnection connection = new SqlConnection(connectionString);
             SQLTableRowCounter qrc = new SQLTableRowCounter("TableName", connection);
             int numRows = qrc.NumberOfRows;
        }
    }
}

Welcome to my new blog

Hey all,

I have had a computer since 1984 when I was 7.  I have been a computer geek most of my life.  I have ten years of intense technical support experience with computer operating systems, networking equipment, and desktop management.

I am currently a Systems Analyst / Developer for LANDesk.

I know FreeBSD, Linux, Windows.  I have worked with the following languages: C++, C#, Java, PHP and dabbled with a couple others.
I have worked with the following database: MySQL, MS SQL, Postgresql.

I need a place to store my knowledge.  I need a location to store my knowledge that I am sure will not disappear.  If I find a good knowledge source, the page may change or the site may be discontinued. Or I may never find a good source and I have to figure something out through trial an error, and a text file on my laptop is probably going to get lost and it also doesn’t help anybody else out.

So I hope this site eventually helps you as much as it helps me.

Thanks,

Rhyous (Jared Barneck)


Console Add-on: LANDesk Support Tools beta 6

Hey all,

It has been a while and there are good reasons for this.

First, I have been working too hard both at work and at home.  I stripped, sanded, and stained my deck with a lot of help from my brother in law.  Never-the-less I have continued this project.

A lot of the DLL file I was using was coded a long time ago by someone else and it was mostly procedural code (even though it was C#), and I rewrote it with a bit more oject oriented-ness. Hopefully, this will make it easy to maintain in the future, not to mention the fact that I am now no longer using functions that I don’t know what they do, cause now I wrote them.

Anyway, here are some of the new enhancements.  They aren’t amazing, because it is the same thing rewritten.  If you find something not working, please let me know.

Release Notes
===============

Version 8.80.3.6
===================
1. Mostly rewrote the SupportTools.dll
    a. Now the SupportTools.xml can be updated and the changes are seen in the console immediately without restarting.
    b. It is now using OS Type instead of OS Name for a filter.
    c. Filtered OS Types no longer show the option disabled, the option is now removed and I didn’t leave in the grayed out option.
    d. Only remote executes check for Remote Control rights, instead of everything checking for those rights.
    e. I slightly altered the XML format.
    f. Moved the SupportTools.xml file to the SupportTools directory.

    g. The Support Tools now are listed in the order placed in the XML, and not automatically sorted, so if you want to change the order you can.
2. Slightly enhanced who.vbs to not crash, but instead give a friendly error for disconnected devices.

3. Added a few options that weren’t there before.

4. Fixed typos in the XML.

5. Added RemoteRegistry.exe (an autoit script recommended to me by user Rich Sterling from community.landesk.com.  Thanks Rich.)

I know most won’t see much difference because they are already using most of the tools in this build.  But there were great strides made that will allow me to now start developing more tools that talk to the agents using LANDesk not RPC, so yeah!

As always you can get the latest link here:

Console Add-on: LANDesk Support Tools

I will keep both versions available for download for now.

I expect my new DLL to be more stable, more rebust, and overwall better.  However, being newly rewritten there is always the chance of an unforseen bug on someone elses system so I am leaving beta 5 downloadable as well.

Latest Version:

LANDesk Support Tools beta 6.exe

Previous Version

LANDesk Support Tools beta 5.exe


How to make renaming of a FreeBSD server easier

I have always felt that renaming FreeBSD was too difficult. I posted about this on the FreeBSD forums, but the response was less than enthusiastic. http://forums.freebsd.org/showthread.php?t=3477

A few people said that servers don’t get renamed often, however, they only cited two companies. I just so happen to have worked as a Network Support Engineer and a Product Support Engineer for almost ten years, working with multiple companies a day. Getting asked how to rename a server or appliance was question that occurred multiple times a month. So many administrators asked how to rename a LANDesk Management Suite server that we had to created a community article that was quite popular and deflected many calls. Unfortunately a LANDesk Management Suite server could not be renamed and administrators were quite disappointed.

I use FreeBSD on VMWare all the time and I am constantly renaming my systems, because I use VMWare and clone one and then have to rename the clone.

Use cases for making renaming of FreeBSD easier

Here are some use cases for making the ability to rename a system easy.

Use case #1 – Imaging or drive cloning

Yes most corporations build a server once and clone it.

They purchase 100 identical hardware servers. They build one server to perfection. They then capture the drive (using and imaging utility).

Then they want to deploy the image and quickly change the name and IP address for the other ninety-nine servers.

NOTE: Companies such as mine (LANDesk) and other Computer Management companies have made the imaging process very slick and have the process automatically give the computers the correct name. We lay down the image, then mount the partition, then take steps to make the computer boot the first time with the correct new name. This is a feature not easily done in most *nix operating systems.

Use Case 2 – Providing an Appliance

If you create an appliance and want to sell it, then I guess this is similar to use case 1. Every client is going to get an appliance that has to be renamed for their company.

Use Case 3 – New IT naming convention

You now have to comply with a standard naming convention for your servers or you had one and it just changed.

Use Case 4 – Two companies merge and they both have similar server names

If one company buys another company and they merge their networks, they may have similar server names. For example, maybe they both have a FreeBSD server and they both cleverly named it “FreeBSD”.

A script to change the hostname on FreeBSD

In order to make it faster to rename a FreeBSD server, I wrote this script.

#!/bin/sh

# Debugging
# debug=true

# Declare functions
checkParams()
{
	if [ $1 -ne 1 ]; then
		showSyntax
	fi
}

showSyntax()
{
		echo 'Invalid syntax.'
		echo '  Usage:'
		echo '  '$0' server.name.com'
		exit 1
}

updateHosts ()
{
	file=/etc/hosts
	if [ $debug ]; then
		echo Updating $file file...
	fi

	fqdn=$1
	hostname=`echo $1 | cut -d . -f 1`

	echo -e "127.0.0.1\t$fqdn $hostname" > /tmp/hosts
	echo -e "127.0.0.1\t$fqdn $hostname" >> /tmp/hosts
	cat $file | grep -v "::1" | grep -v "127.0.0.1" | grep -v "#" >> /tmp/hosts
	mv -f /tmp/hosts $file

	if [ $debug ]; then
		echo Finished updating $file file...
	fi
}

updateRcConf ()
{
	file=/etc/rc.conf
	if [ $debug ]; then
		echo Updating $file file...
	fi

	echo hostname=$1 > /tmp/rc.conf
	cat $file | grep -v "hostname" >> /tmp/rc.conf
	mv -f /tmp/rc.conf $file

	if [ $debug ]; then
		echo Finished updating $file file...
	fi
}

updateApacheConf ()
{
	file=/usr/local/etc/apache*/httpd.conf
	if [ $debug ]; then
		echo Updating $file file...
	fi

	cp -f $file /tmp/httpd.conf
	sed -i .bak "s/ServerName[^:]*/ServerName $1/" /tmp/httpd.conf
	mv -f /tmp/httpd.conf $file

	if [ $debug ]; then
		echo Finished updating $file file...
	fi
}

# Run
checkParams $# $1
updateHosts $1
updateRcConf $1
updateApacheConf $1

Ideas for continually improving the renaming process

The hostname command could have a switch to try to rename the box permanently. It changes the hosts file, the rc.conf, and calls the port scripts in question.  The port scripts could be handled in either of the following ways.
  1. A folder could be created called /usr/local/etc/rename.d and each port could over the course of the next few years start building a script that is able to edit their configuration files and put i the correct name.
  2. Each port in their startup script, /usr/local/etc/rc.d/appscript.sh, could have a rename switch.
It won’t be simple, and it will take years for different ports to start supporting such a feature, but it could work for FreeBSD or Linux quite easily.