Monday, July 21, 2008

Using LINQ to Read a CSV File

I recently wrote a windows application which plots my checking account balance on a graph. In this application, I needed to import the financial data from a CSV (comma separated values) file. LINQ's ability to iterate over a collection of objects made this task easy:

IEnumerable lines = File.ReadAllLines("c:\checking.csv");

var query = from line in lines
let x = line.Split(',') //x will be a new, anonymous type
where x[0].Length > 0 //skip blank lines
select new
{
Date = DateTime.Parse(x[0].Replace("\"", string.Empty)), //remove double quotes
Description = x[4].Replace("\"", string.Empty),
Amount = Convert.ToDecimal(x[1].Replace("\"", string.Empty))
};

foreach(var i in query)
{
Console.WriteLine("Date: " + i.Date.ToString());
Console.WriteLine("Desc: " + i.Description);
Console.WriteLine("Amount: " + i.Amount.ToString());
}

Wednesday, January 30, 2008

Programmatically read AssemblyInfo attributes in a .NET 2.0 web application

As a developer, I can set version information for an application in the AssemblyInfo.cs file in a .NET application. I like to make the version number visible to someone who doesn't have access to the source or compiled code.

Here are a couple of ways to retrieve this information programmatically in C# using classes from the System.Reflection namespace:

.NET 1.1 ASP.NET Web Project, .NET 1.1 Windows Application, .NET 2.0 Windows Application
string version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();

.NET 2.0 ASP.NET Web Project
string version = System.Reflection.Assembly.Load("AssemblyName").GetName().Version.ToString();
where "AssemblyName" matches the assembly name in the web project's application properties (to open the project properties, right-click your web application, click Properties, click the Application tab, and view or change the Assembly name)

Comments or suggestions? Post below.

Saturday, August 4, 2007

Playing Favorites

Can a man favor one piece of code over another? Will the neglected code lead a life of misery because it did not know it's father's love? No, unless you're on the verge of writing some AI that needs to be reviewed before you go any further...

Over the years, I have written lots of T-SQL and .NET code. I'm always on the lookout for development language enhancements that make it easier to accomplish the same tasks with fewer lines of code. Among my favorite enhancements are sorting and filtering with C# 2.0 Generics.

Let's start with a simple Employee object:

public class Employee
{
string _firstName, _lastName;
decimal _salary;
public Employee(string firstName, string lastName, decimal salary) { _firstName = firstName; _lastName = lastName; _salary = salary; }
public string FirstName
{
get { return _firstName; }
}
public string LastName
{
get { return _lastName; }
}
public decimal Salary
{
get { return _salary; }
}
}


Let's create a Generic list of Employees:

List<employee> employeeList = new List<employee>();
employeeList.Add(new Employee("John", "Walker", 35000M));
employeeList.Add(new Employee("April", "Aagard", 45000M));
employeeList.Add(new Employee("Joann", "Wilten", 50000M));


List<T>.ForEach returns all of the items in the list:

Console.WriteLine("List all employees");
employeeList.ForEach(delegate(Employee em) {
Console.WriteLine(
string.Format("Name: {0} {1}, Salary: {2}",
em.FirstName, em.LastName, em.Salary.ToString()));});
Console.WriteLine();


List<T>.FindAll filters the list:

Console.WriteLine("Filtered by salary (where salary > 40000)");
List<employee> wellCompensatedList = employeeList.FindAll(delegate(Employee em) { return em.Salary > 40000M; });
wellCompensatedList.ForEach(delegate(Employee em)
{
Console.WriteLine(
string.Format("Name: {0} {1}, Salary: {2}",
em.FirstName, em.LastName, em.Salary.ToString()));
});
Console.WriteLine();


List<T>.Sort reorders the list:

Console.WriteLine("Sorted by last name ascending");
employeeList.Sort(delegate(Employee em1, Employee em2) { return em1.LastName.CompareTo(em2.LastName); });
employeeList.ForEach(delegate(Employee em)
{
Console.WriteLine(
string.Format("Name: {0} {1}, Salary: {2}",
em.FirstName, em.LastName, em.Salary.ToString()));
});
Console.ReadLine();


As you can see, the Generic list methods FindAll, ForEach and Sort, when combined with anonymous methods, allow you to easily manipulate your lists. Clean and simple code. No wonder it's my favorite. What code is your favorite?

Monday, July 30, 2007

Old School Keyboard Shortcuts in Microsoft SQL Server Management Studio

Want to use Query Analyzer keyboard shortcuts, like Ctrl-Shift C (comment the highlighted lines) and Ctrl-Shift R (uncomment the highlighted lines) in Microsoft SQL Server Management Studio (SSMS)? Easy. Open SSMS's Options (Tools -> Options), go to Environment -> Keyboard and change the Keyboard scheme to SQL Server 2000 and click OK.

Thursday, July 19, 2007

.NET Setup Project Custom Actions

Ever created a .NET windows service in Visual Studio, added a setup project, set all of the properties to install and display the correct information during installation, only to have the service not show up in Windows' Services Microsoft Management Console (mmc)? You probably forgot to add the custom actions.

To add custom actions to your setup project:
1) Click the setup project in Solution Explorer
2) Click the Custom Actions Editor button at the top of Solution Explorer
3) Right-click on the Custom Actions node
4) Click Add Custom Action
5) In the Select Item in Project dialog box, select Application Folder from the dropdown
6) Click OK

That's it. Right-click the setup project, and click Install. Your service should now appear in the Services mmc. Just remember to close the Services mmc before you uninstall, or undesired consequences may result. Good luck!

Wednesday, July 18, 2007

Microsoft Certified Professional Developer (MCPD) certification

Two years. It's been two years since I received my Microsoft Certified Application Developer (MCAD) certification for Microsoft .NET 1.0 and 1.1. Now, I'm studying for the MCPD certification for .NET 2.0. The practice tests are similar to the tests leading up to the MCAD, so I'm not worried about failing the test because of formatting changes. In fact, I've been programming in .NET 2.0 for nearly a year, and most of the practice questions are familiar.

Because I already have my MCAD, upgrading to the MCPD requires that I pass only one test. I have chosen the Windows developer MCPD path (test 70-552), because most of the .NET 2.0 applications that I write at work are windows applications.

The reason that I want to complete Microsoft certifications is that my employer pays for the study materials and tests, it looks good to potential employers, and hey, this is a good substitute for going back to school (who would hire me if I had a Ph.D., anyway?).

I plan on taking test 70-552 mid-late August, depending on how much time I can spend studying between now and then.

Do you have any of the Microsoft .NET certifications? Have they helped you in your career? Please post in the comments below. Thanks.

Friday, June 29, 2007

Include Column Headers When Copying the Results

In Microsoft SQL Server Management Studio, there is now an option to include column headers with the rows that you copy from the results pane. For example, when I copy the following records from SQL Server Management Studio and pasting into Excel, I now know the names of the columns:

ID First Name Last Name
1 Robert Doe


To enable this feature in Management Studio, click Tools -> Options -> Query Results -> SQL Server -> Results to Grid and check 'Include column headers when copying or saving the results' and click OK. Click on the screenshot below for a screenshot.