Implementing a 3-Tier architecture with C# – Part 4



Up to now, we have finished implementing the data access layer. However, we can reduce the dependency between the deriver DAL classes and Web.config file. As you remember, we have specified the DB provider name in Web.config file so that DAL classes must have access to this file to read the provider name. Another method to specify the provider type is using custom attributes.

Firstly, in the DataAccessLayerBase namespace, we declare a public enum type named ProviderType:

public enum ProviderType
{
SqlServer,
Odbc,
OleDb
}

We also remove the ProviderName property from DALHelper class, and instead, add a new internal method, as bellow, to get a string representation of each ProviderType member:

internal static string GetProviderTypeName(ProviderType providerType)
{
switch (providerType)
{
case ProviderType.SqlServer: return “System.Data.SqlClient”;
case ProviderType.Odbc: return “System.Data.Odbc”;
case ProviderType.OleDb: return “System.Data.OleDb”;
default: return “System.Data.SqlClient”;
}
}

The custom attribute we need for specifying the provider type, must have a public property of type ProviderType. We also add a constructor, with a positional parameter of type ProviderType, to our custom attribute class:

[AttributeUsage(AttributeTargets.Class)]
public sealed class DbProviderTypeAttribute : Attribute
{
public ProviderType PrType
{
set;
get;
}
}

The AttributeUsage attribute indicates that this custom attribute can be applied to classes only.

To make this attribute effective, we need to alter the base DAL class’s constructor as bellow:

first we must check to see if the DbProviderTypeAttribute attribute has been applied to the derived DAL class:

if (!this.GetType().IsDefined(typeof(DbProviderTypeAttribute), false))
throw new System.Exception(“DbProviderTypeAttribute must be applied to DAL class”);

The above code examines the existence of DbProviderTypeAttribute and throws an exception of it does not exist.

Then, the following piece of code, extracts the instance of DbProviderTypeAttribute from the class’s metadata, and uses the value of it’s PrType property to set the ProviderName :

List<object> t = this.GetType().GetCustomAttributes(typeof(DbProviderTypeAttribute), false).ToList();
DbProviderTypeAttribute Provider = t[0] as DbProviderTypeAttribute;
ProviderName = DALHelper.GetProviderTypeName(Provider.PrType);
_ProviderFactory = DbProviderFactories.GetFactory(ProviderName);

That’s it. This way we have reduced the coupling between our UI (web.config file) and the DAL class. When developing a derived DAL class, we have to apply DbProviderType attribute to it:

[DbProviderType(PrType=ProviderType.SqlServer)]
public class PersonDAL : DALBase
{ …

Implementing the business classes

The implementation of business classes are fairly easy. A business class is a bridge between the presentation layer and the data access layer, perform business checks, controls concurrencies and even might control the business transactions.

The business classes can be either static or instance classes. Each business method can create one or more instances of the required DAL classes. However, since each DAL class has it’s own connection object (innerConnection property), system transactions would better be controlled in business methods. This may even solve the issue that is raised when a layered architecture needs to control both business and system transactions.

The easiest way to control the transactions, is using System.Transaction name space and TransactionScope class. The illustration of TransactionScope requires an indipendent post, but for now, lets say that transaction begins when an instance of TransactionScope class is created and it is commited when the .Complete() method is called:

using (TransactionScope scope = new TransactionScope())

{

…..

scope.Complete();

}

if an exception is thrown, the transaction will roll back :

using (TransactionScope scope = new TransactionScope())

{

PersonDAL PDAL= new PersonDAL();

….

ChildDAL CDAL= new ChildDAL();

PDAL.Update(personDT);

CDAL.Update(childDT);

scope.Complete();

}

Note that MSDTC service must be running on the server machine.

so far, the definition of business classes requires no additional settings. however, when developing the presentaion layer, we will come back and make some minor changes to make our bisuness classes compatible with UI components.

A sample business class might look like this:

public class PersonBiz
{

private PersonDAL innerDAL = new PersonDAL();
public DataTable FetchAll(int startRowIndex, int maximumRows)
{
PersonEntity entity = new PersonEntity();
innerDAL.Fill(entity, startRowIndex, maximumRows);
return entity;
}

public void Update(System.Data.DataTable table)
{
// validate fields/perform business checks and throw an exception if a criteria is not met
innerDAL.Update(table);
}
:

:

}


Advertisements

3 thoughts on “Implementing a 3-Tier architecture with C# – Part 4

  1. Menahem Hershcovitz says:

    Hello

    I am building your project in .NET 2.0 and the following code has build errors :

    public ProviderType PrType
    {
    set;
    get;
    }

    What is the right syntax in .NET 2 ?

    Thanks,
    Meny
    **********
    Hi,
    I have written that code with C# 3.0 and VS 2008. In C# 2.0 you can not declare a property this way. Please change the code, and other similar codes, to the following one:

    private ProviderType _PrType;
    public ProviderType PrType
    {
    set { _PrType = value;};
    get { return _PrType;};
    }

  2. Menahem Hershcovitz says:

    This code:
    private ProviderType _PrType;
    public ProviderType PrType
    {
    set { _PrType = value;};
    get { return _PrType;};
    }

    doesn’t compile either

    Can you post all the class ?

    Why did you use the sealed option ?

    Thanks
    Menahem Hershcovitz

    Hi again,
    I think you should compile the code with VS 2008 because changes will be too many.
    We seal the Attribute classes for security reasons.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s