|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IndexIntroductionThis is the last article of this series. In the first article we've seen how to give descriptive information about a class using attributes. In the second article we've seen how to extract that information using the Designing the DAL libraryDuring the creation of this DAL library I wanted to create it so it could be used either with a SQL Server data provider or an OleDb data provider. It could also be extended to other data providers. We can divide this library in the following parts: Utility classesclass DALQueryBuilderAs mentioned in the first article this class helps in the construction of SQL statements to update an object in the database class DALParameterA generic parameter class to be used in stored procedures class DALExceptionIt's aSystem.Exception derived class. It's thrown whenever an exception occurs in our database operations. It provides more information about the error that happened.
Attribute classesAll the classes that are derived from DAL itselfclass DALEngineThe abstract base class that does database operations, making the database programming a lot easier. It has virtual and abstract methods were each data provider has a different implementation. More than methods to return DataSets, DataReaders from a database it has methods that handle objects marked with the DAL attributes. class DALSqlEngineA SQL Server implementation of DALEngine class DALOleDbEngineAn OleDb implementation of DALEngine A Closer Look at the DALEngine classThis is the declaration of the public abstract class DALEngine : IDisposable
{
//
// private data members
//
IDbConnection conn = null;
string connectionString = "";
ArrayList parameters = new ArrayList();
bool canClose = true;
// constructor
public DALEngine(string connectionString);
public bool CanClose;
public string ConnectionString;
protected IDbConnection Connection;
protected ArrayList Parameters;
public void Close();
public void Dispose();
//
// methods that must be override with a specific data provider
// implementation please see the implementation of DALSqlEngine
// or DALOleDbEngine
As you may be thinking we will only that a look at the last 6 methods. The other ones are easy to understand since there are a lot of similar implementations out there. The The method The methods BenefitsFirst of all using the DAL itself will make your database programming a lot easier. Even if you don't intend to do database programming as I do, I strongly recommend using a DAL library that already have tedious and repetitive tasks implemented. You don't have to use this one, but at least use one. But if you do use business objects to work with the database this library will save you a lot of time and effort. There's only a piece of source code that needs to be reviewed when a change in the database happens. And it can be done using a tool of your own, doing the opposite of the tool we created in the second part of this article. To show you how easy it is to get/update objects from the database I included a sample application along with the full DAL library code. There's a code fragment of this sample application below so you can have a clue of it's strength. For sure the DAL has a lot of bugs, and that's one of the reasons I posted this code here. Maybe you could have better solutions and code to accomplish the library goals. Please feel free to send me questions and contributions as I'm really interested in improving this library. To develop the sample application I created my own DAL class deriving from DALSqlEngine, since I would be using SQL Server. That's the code of my DAL class: public class DAL : DALSqlEngine
{
const string CONN_STRING = "server=localhost;uid=sa;pwd=;database=pubs";
public DAL() : base(CONN_STRING)
{
}
public ArrayList GetCustomerDependents(Customer customer)
{
ArrayList result = new ArrayList();
RetrieveChildObjects(customer.Id, result, typeof(CustomerDependent));
return result;
}
public void UpdateCustomerDependents(Customer customer)
{
UpdateObjects(customer.Dependents);
}
}
Simple, isn't it? Now the application code, it's just inserting/updating contact/customers and customer dependents. public static void Main()
{
DAL dal = new DAL();
try
{
Contact contact = new Contact();
contact.Name = "Joao Cardoso";
contact.Age = 23;
contact.Address = "Av. Rio Branco, 202/121";
contact.Address2 = "Centro";
contact.PostalCode = "09029-901";
contact.City = "Sao Paulo";
contact.State = "SP";
contact.Country = "Brazil";
dal.UpdateObject(contact);
Console.WriteLine(contact);
Contact joaoCardoso = (Contact)dal.RetrieveObject(1, typeof(Contact));
joaoCardoso.Age++;
Console.WriteLine(joaoCardoso);
Console.WriteLine("");
Customer customer = new Customer();
customer.Name = "Paul Noyter";
customer.Age = 34;
customer.Address = "All St, 2202/2121";
customer.Address2 = "Downville";
customer.PostalCode = "90931";
customer.City = "Los Angeles";
customer.State = "CA";
customer.Country = "United States";
customer.TotalPurchased += 1900.87M;
customer.NumberOfPurchases++;
dal.UpdateObject(customer);
Customer paul = (Customer)dal.RetrieveObject(1, typeof(Customer));
Console.WriteLine(paul);
paul.TotalPurchased += 100M;
paul.NumberOfPurchases++;
dal.UpdateObject(paul);
if (paul.Dependents.Count == 0)
{
CustomerDependent dependent = paul.NewDependent();
dependent.Name = "Marie Noyter";
dependent.Age = 31;
paul.Dependents.Add(dependent);
dependent = paul.NewDependent();
dependent.Name = "Mark Noyter";
dependent.Age = 10;
paul.Dependents.Add(dependent);
dependent = paul.NewDependent();
dependent.Name = "Claudia Snorg";
dependent.Age = 32;
dependent.Relationship = CustomerRelationship.Friend;
paul.Dependents.Add(dependent);
dal.UpdateCustomerDependents(paul);
}
else
{
Console.WriteLine("Dependents of {0}", paul.Name);
foreach(CustomerDependent dependent in paul.Dependents)
{
Console.WriteLine("<Dependent>{0} - {1} [{2}]", dependent.Id,
dependent.Name, dependent.Relationship);
dependent.Relationship = CustomerRelationship.Family;
}
dal.UpdateCustomerDependents(paul);
}
}
finally
{
dal.Dispose();
}
}
LimitationsOf course it has limitations. Some can be solved by extending the DAL or the attributes. If you don't use an auto number key column the only way you can update your object is using stored procedures. The problem is that DAL can't figure out if an object should be inserted or updated in the database. You could extend the DAL so that it checks for a known attribute or interface that provides the information needed; Currently it doesn't support tables with more than one key column; Performance isn't fast as pushing ConclusionThere a lot of ways to do database programming in the .NET world. Visual Studio .NET enables you to use Typed | ||||||||||||||||||||