I am a casual C# programmer, not formally trained in OOP at all; mostly I focus on Transact-SQL in SQL Server, and so when I write C# apps I get grief about the constructs and methods I use. Here is a simple app I wrote for this blog post - it was not meant to be a production app, and performance is certainly not a priority, but I would like to become better at writing optimal code naturally.
The purpose of the code is quite simple - for 100,000 cycles I need to generate a random name and number from a SQL Server stored procedure, then write those values to a table . After that, read 100 random rows from the table, 1,000 times, and not really care what is done as you iterate through the 100 rows.
The point of the exercise was to profile the effects of encryption on the application. So what the reader loop does is not really material and does not need to be optimized, it is just there to take up time and be the same in both cases. Also it should be noted that the multiple connections are intentional - it is supposed to simulate - without getting into multi-threading or multiple instances of the app - all of the overhead you would see in a highly concurrent app (even though, deep down, this still executes serially).
Items that were pointed out to me (and that I'd like to better understand):
for
is better thanwhile
- Variable declaration at the top is bad
- Code is bloated
- Legibility is bad
I am also sure there is a better way to time the performance of the code, other than dumping the current clock time to the console.
using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
namespace AEDemo
{
class Program
{
static void Main(string[] args)
{
using (SqlConnection con1 = new SqlConnection())
{
Console.WriteLine(DateTime.UtcNow.ToString("hh:mm:ss.fffffff"));
string name;
string EmptyString = "";
string conString = ConfigurationManager.ConnectionStrings[args[0]].ToString();
int salary;
int i = 1;
while (i <= 100000)
{
con1.ConnectionString = conString;
using (SqlCommand cmd1 = new SqlCommand("dbo.GenerateNameAndSalary", con1))
{
cmd1.CommandType = CommandType.StoredProcedure;
SqlParameter n = new SqlParameter("@Name", SqlDbType.NVarChar, 32)
{ Direction = ParameterDirection.Output };
SqlParameter s = new SqlParameter("@Salary", SqlDbType.Int)
{ Direction = ParameterDirection.Output };
cmd1.Parameters.Add(n);
cmd1.Parameters.Add(s);
con1.Open();
cmd1.ExecuteNonQuery();
name = n.Value.ToString();
salary = Convert.ToInt32(s.Value);
con1.Close();
}
using (SqlConnection con2 = new SqlConnection())
{
con2.ConnectionString = conString;
using (SqlCommand cmd2 = new SqlCommand("dbo.AddPerson", con2))
{
cmd2.CommandType = CommandType.StoredProcedure;
SqlParameter n = new SqlParameter("@LastName", SqlDbType.NVarChar, 32);
SqlParameter s = new SqlParameter("@Salary", SqlDbType.Int);
n.Value = name;
s.Value = salary;
cmd2.Parameters.Add(n);
cmd2.Parameters.Add(s);
con2.Open();
cmd2.ExecuteNonQuery();
con2.Close();
}
}
i++;
}
Console.WriteLine(DateTime.UtcNow.ToString("hh:mm:ss.fffffff"));
i = 1;
while (i <= 1000)
{
using (SqlConnection con3 = new SqlConnection())
{
con3.ConnectionString = conString;
using (SqlCommand cmd3 = new SqlCommand("dbo.RetrievePeople", con3))
{
cmd3.CommandType = CommandType.StoredProcedure;
con3.Open();
SqlDataReader rdr = cmd3.ExecuteReader();
while (rdr.Read())
{
EmptyString += rdr[0].ToString();
}
con3.Close();
}
}
i++;
}
Console.WriteLine(DateTime.UtcNow.ToString("hh:mm:ss.fffffff"));
}
}
}
}