Jaycent Drysdale

February 2008 - Posts

System.Data.GenericClient : A custom Data Access Component

Developers often find themselves having to connect to data in a variety of datasources ranging from MS Access  to large scale relational databases such as Oracle, SQL Server, MySql etc. Each different datasource type typically requires importing a different .Net provider-specific namespace for working wth a specific database. For instance, to connect to an Oracle Database the consuming application needs to import the System.Data.OracleClient Namespace and untilize classes such as OracleCommand, OracleDateReader etcettera. To connect to SqlServer applications developers import the  System.Data.SqlClient namespace into their applications and program against the classes provided by the namespace.  The net effect of having multpile provider specific namespaces is that your DAL components are rarely ever portable, with each different database type normally requiring provider specific code.

System.Data.GenericClient is a simple but generic custom built data access component that solves some of the issues outlined above. System.Data.GenericClient provides a very simple but familiar API that can be configured declaratively in an application configuration file as well as programmatically in your DAL. Below I'll take a look at using System.Data.Generic to connect to various datasources using a consistent API.

Here's what you need to do to get started using System.Data.GenericClient in your applications:

  1. Download the zip file at the link provided below . Extract the contents, then add a reference in your application to the extracted System.Data.GenericClient.dll file.

  2. Open up your aspplications config file and declare an appsettings entry as shown below:
    <appSettings>
               <
    add key="System.Data.GenericClient.DefaultConnectionStringName" value="mysqlConnectionString" />
    </
    appSettings>

  3. Declare a connectionstring entry. Make sure the name of this connection string matches the appsettings entry value specified above. In this case, the connectionstring entry name should be specified as "mysqlConnectionString. Provide a valid MySql Connection string. See example below:

    <connectionStrings>
          <
    add name="mysqlConnectionString"
          
    connectionString="Network Address=serveradress;
           Initial
    Catalog='mydb';User Name='sa';Password='pwd'" 
           providerName
    ="MySql.Data.MySqlClient" />
    </connectionStrings>

  4. Write data access logic to connect to the database. Below is an example of how to return a datatable object from the datasource

    using (System.Data.GenericClient gClnt = new GenericClient())
    {
         gClnt.Command.CommandType = CommandType.Text;
         gClnt.Command.CommandText =
    "select * from employees";
        
    using (DataTable dt = gClnt.ExecuteDataTable())
         {
             
    this.dataGridView1.DataSource = dt;
         
    }
    }

The code snippet above shows how simple it is to use System.Data.GenericClient to access data from mySQL in a provider independent format.  For each aditional datasource your application needs to connect to, specify a valid connection string in the applications configuration file as outlined above, then specify a valid command text or stored procedure on GenericClient's command object. 

See below for a list of operations supported by the GenericClient object:

  1. public virtual int ExecuteNonQuery()
    Use this method to execute an update, insert or delete operation on the underlying datasource

  2. public virtual string ExecuteXML()
    Use this method to execute a query on the underlying datasource. Returns data in xml format

  3. public virtual DataTable ExecuteDataTable()
    Use this method to execute a query on the underlying datasource. Returns a datatable object

  4. public virtual object ExecuteScalar()
    Use this method to execute a query on the underlying datasource. Returns a scalar object

System.Data.GenericClient remains a work in progress. In addition to the features highlighted above, you will find other features in the namespace. These and other features will be further refined and documented in future updates.

File Download: System.Data.GenericClient.zip 

Want a copy of the source code? Send email to jaycentdrysdale@hotmail.com

File System search via LINQ to Objects

LINQ provides a standard way for developers to query data in diverse locations, ranging from in memory objects, XML data, or relational data living in an SQL Server Database.Lets take a look at a scenario where we use Linq to objects to query a directory on the local drive for files that match a given extension, and show the results in a Datagrid control.

Here is the plan of action for the application

  1. Create a function to return a list of all the files in a directory.  We will call this method GetFiles, it will take one string parameter representing the base search directory, and will return a strongly typed list of FileInfo Objects.
  2. Use Linq to Objects to filter the returned list for files that matches a user-specified file extension.
  3. Bind the results to a grid
Lets start by taking a look at the GetFiles function:

public
static System.Collections.Generic.List<FileInfo> GetFiles(string sPath, string sFileExtension)
{
     
DirectoryInfo _dirInfo = new DirectoryInfo(sPath);
     
return System.Linq.Enumerable.ToList(_dirInfo.GetFiles(string.Format("*{0}",sFileExtension), SearchOption.AllDirectories));
}

The GetFiles() function uses objects from the System.IO namespace to do the heavy lifting of searching the file system. Results are returned in a strongly typed list of FileInfo Objects.

Next we will look at the code that calls the GetFiles method defined above, and uses Linq to filter the list for the given file type. You would typically put this code in the click event for a button control on a windows form.

//get all files contained in the path supplied by the user
System.Collections.Generic.List<FileInfo> _theFiles = GetFiles(c:\myDirectory, ".doc"); 

//we now have a list of files...next we use LINQ to query the file list and sort the results by name
var _files = from file in _theFiles 
     
orderby file.Name 
                
select file;

this.dataGridView1.DataSource = _files.ToList();

And there you have it. Note the use of the orderby clause to sort the results before you bind the results to the grid. 

Posted: Feb 15 2008, 11:21 AM by jaycent | with 29 comment(s) |
Filed under: , , ,
Extension Methods: A simple example

If you've been developing software for any significant lenght of time, chances are you have compiled(for want of a better word) a repository of helper functions that have, over time, become valuable to you as you make your way through various applications. Extension Methods allow us to extend our custom and existing CLR types to include new functionality. These new functionality might already exist in the form of helper functions scattered throughtout our applications. For example, You might have a helper function that converts a string value to Proper Case. Extension methods allow us to "add" this ToProperCase() functionality to the primitive System.String type as if it were a built in method of the type. 

In this post, I'll share with you a simple example of how I used extension methods to extend the sealed System.DateTime native type to include a
ToFriendlyDateString() method. Extension Methods are new in the .Net Framework 3.5.

The idea behind the ToFriendlyDateString() method is representing dates in a user friendly way. For example, when displaying a news article on a webpage, 
you might want articles that were published one day ago to have their publish dates represented as "yesterday at 12:30 PM". Or if the article was publish today,
show the date as "Today, 3:33 PM". 

The code snippet below shows the logic that will represent our extension method. Note the Namespace declaration, and the signature for the class definition. Note also the use of the this keyword when describing the input parameter for the ToFriendlyDateString() method. I'll eloberate on these later in this discussion.

namespace Utils
{
     public static class Extensions
       
{
            
public static string ToFriendlyDateString(this DateTime Date) 
             
{
                    
string FormattedDate = "";
                    
if (Date.Date == DateTime.Today)
                    
{
                           FormattedDate =
"Today";
                    
}
                    
else if (Date.Date == DateTime.Today.AddDays(-1)) 
                    {
                           FormattedDate =
"Yesterday"; 
                    }
                    
else if (Date.Date > DateTime.Today.AddDays(-6))
                    {
                           // *** Show the Day of the week
                          
FormattedDate = Date.ToString("dddd").ToString(); 
                    }
                    else
                   
{
                          FormattedDate = Date.ToString(
"MMMM dd, yyyy");
                    }

                  
//append the time portion to the output
                 
FormattedDate += " @ " + Date.ToString("t").ToLower();
                 
return FormattedDate; 
             }
        }
} 

When creating extension methods, here are the rules

  • You must define a namespace for your class.  Utils in the snippet above (Namespaces are not a strict requirement, but good practice nevertheless)
  • The class that contain the extension method must be decorated with the static modifier, and its visibility must be public
  • The class must contain a static member, which will act as the extension method. This method must be public and must take one or more parameters, the first which must be a derivitive of the type you are extending. The first parameter definition must be preceeded by the this keyword

Extension methods are defined as static methods but are called by using instance method syntax. Their first parameter specifies which type the method operates on, and the parameter is preceded by the this modifier. Extension methods are only in scope when you explicitly import the namespace into your source code with a using directive. See example below showing how we might use the ToFriendlyDateString() method in our applications:

using Utils;

......

DateTime dt = new DateTime(2008, 2, 10, 8, 48, 20);
Console.WriteLine(dt.ToFriendlyDateString());

For further details on Extension Methods, check out this MSDN link: http://msdn2.microsoft.com/en-us/library/bb383977.aspx

Object Oriented Programming Refresher

Recently I was challenged by a colleague who asked some very basic questions relating to object orient programming. I know these concepts very well, but sometimes you have to stop and think twice about them, especially if most often than not, you do not implement these concepts in your day to day programming activities. As developers, we often find ourselves in situations where the need to get things out the door and into production tend to encourage us to not think about doing things the right way, but instead, getting the work done in the least possible time.  Object Oriented concepts are something every serious developer should know inside out. Sure you can get by without practicing it, but that approach might come back to haunt you down the road.

Classes are the foundation of Object Oriented Programming. Business Logic code should be seperated into groups of related classes that satisfy a business need. There should be a clear seperation of concerns. When planning a development strategy for our applications, we should at all times try to envision our applications as being seperated into three logical tiers. Strictly speaking, having three logical tiers doesnt dictate that our apps must to be deployed physically as a three tier app...all the tiers could live on one one physical machine, or they could be deployed accross three different machines. They could also be deployed on multiple machines in the enterprise, in what is known as an n-tier architecture.  Our apps will perform much better when we distribute the processing requirements accross multiple machines...business logic components run on machine A, Data Access components run seperate machine, and the front end logic running on a clinet pc or web server somewhere else. Microsft Transaction Server, and now Enterpise Services can act as a broker for our components living in the data access and business logic tiers, and offer such services as transactions support, object pooling, which promotes better scaling applications.

So, what is an abstract class. What is a sealed class. What is the difference accessibility methods out there that I can apply to my classes and methods, and why do I need them? What are interfaces? when is it useful to use an interface? These are the questions that rolled through my head when I was first introduced to OOP years ago. Over time, as you develop more business level applications, the importance of these concepts become clearer.

Inheritance is a pupular term among the OOP purists. So what is Inheritance, and how does it relate to OOP? Perhaps the best way to describe this would be to imagine a hypothetical situation where you are building an app that requires you to Mainatin a list of employee records. All employees must have an employeeID, they must have a first name, and they must have a departmentID etc. In addition, there are some employees that work on a part-time basis, and some that work full-time.

Looking at the above scenario, we have indentified the need for an employee class to service our application. but before we start building our employee class, we need to take a closer look at how that class will be implemented. There are common features that all employees have, but there are also some features that are specific to  the full-time employee and others that are specific to the part-time employee. For instance, when we calculate the monthly pay for the full-time employee, the logic might be different from what we do when we calculate the salary of the guy that is employed part-time.  It might help if we define a baseline Employee class that contain the common functionality, properties etc, and then further extend these classes in other derived classes to inplement the specific functionality. So at the root, we might create an employee class,  and two derived classes: FullTimeEmployee and ParttimeEmployee. Both these classes will be based on the base Employee class and will inherit any functionality exposed, but will further provide indiviual methods that will be used to calculate an employee's salary.

By marking our employee class as Abstract, we are marking it as a class that cannot be instantiated directly...we are saying that this class exists only to be further refined through inheritance. The exact opposite scenario to that would be to mark our class as sealed, which would mean it cannot be further refined through inheritance.

The definition for our base employee class might look like this:

public abstract class Employee
{
}

The definiton for the derived classes might look like so:

public
sealed class PartTimeEmployee:Employee
{}

public sealed class FullTimeEmployee:Employee
{}


Selected data and function members defined in the Employee class will be avaialable in both the derived classes. Data Members such as firstname, lastname, deptID, employeeID are common to all employees are defined on the Employee base class. The Employee base class will also contain a method called CalculateWages, which will contain no functionality, but will tell any class that implements the Employee class that it must implement a CalculateWages method. In the base class, the signature for the calculateWages Method might look like this: 

public
abstract decimal CalculateWages();

The CalculateWage() method in the base Employee class could alternatively be decorated with the virtual modifier instead of abstract. The difference is that the virtual modifier allows the base class to put implementation code in the method, and allows the derived class to decide wether or not it wants to override the implemementation provided by the base class. If the derived class wants to overide the method in the base class, it would implement the method using the following signature:

public override decimal CalculateWages()
{}

The scenario looked at above describes a very simple example of how we might implement a simple employee class in one of our applications. Of course, there is much more to object oriented programming, to much to be described in a single blog post. Of course, there are many different ways to implement OOP...for instance, the employee base class described above could be implemented as an interface instead of as an abstract class. 

In Part 2 of this 4 part series, I'll take a look at other class modifiers, and also some of the accessibility options that we have available for exposing our classes to the outside world and what they mean for our classes. I'll also take a look at Interfaces, and how they can be used in the Employee list management scenario described in this article.

More Posts