Enterprise Library 5 is still only available as preliminary source code on CodePlex so it is probably way too early for most people to start using it. I, however, like to get my hands dirty and dig through the source code to see all the new changes. Any code you see in this post is preliminary and subject to change. I am working from changeset 61455 in this post.
Data Access Application Block
The most popular application block in Enterprise Library is the Data Access Application Block. Developers use it as a means of accessing data from a large range of supported databases and a few O/R Mappers have used the DAAB as the ADO.NET Engine under the covers. I absolutely love the Data Access Application Block and have used it and customized it for years.
If you are familiar with the DAAB, you will know that its intent is to make accessing stored procedures convenient. Although the DAAB supports more than just stored procedures, many of the methods on the base Database Class, like ExecuteReader, ExecuteScalar, and ExecuteNonQuery, for example, have a common method signature that takes a stored procedure name and list of parameter values to make calling a stored procedure effortless:
public IDataReader ExecuteReader(string storedProcedureName, params object[] parameterValues)
When working with ADO.NET and stored procedures these methods have sheltered us from all the complexities of connection management and best practices around performance, exception handling, etc.
O/R Mapping
As time has progressed, however, software developers are often not thinking about database tables and rows in their applications, but collections and classes. A row in a Contacts Table, for example, is now often mapped to a Contact Class in your .NET Application and several rows are often mapped to a custom ContactCollection Class or collection-based class in the .NET Framework.
When using the Enterprise Library DAAB with custom classes, one has to map the results of an IDataReader or IDataRecord to these custom classes, whether it be a factory method on the class, a stand-alone class factory, heavy use of reflection in a generic class, etc. The ContactFactory Class below is a simplified version of something you might use in your applications.
public class Contact
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
}
public static class ContactFactory
{
public static Contact Create(IDataReader dr)
{
return new Contact
{
Id = dr.GetInt32(0),
Name = dr.GetString(1),
Email = dr.GetString(2)
};
}
}
The Contact and ContactFactory Classes then get used in your data access layer in some sort of data access object ( DAO ), repository, or other datamapper class.
public class ContactsDAO
{
private readonly Database _database;
public ContactsDAO(Database database)
{
_database = database;
}
public Contact FetchById(int id)
{
Contact contact = null;
using (IDataReader dr = _database.ExecuteReader("FetchContactById", id))
{
if (dr.Read())
contact = ContactFactory.Create(dr);
}
return contact;
}
}
Although your code will certainly be more robust and the strategy will vary, the spirit of the code above is pretty typical of most datamapper classes that use the DAAB to return classes and collections using the standard Database Class API. Given the tendency to write this type of code over and over again, the Enterprise Library Team has decided to create some Extension Methods on the Database Class in Enterprise Library 5 to help with this simple mapping.
Enterprise Library 5 DatabaseExtensions Class and ExecuteSprocAccessor
In the current preliminary release of Enterprise Library 5, you will find a DatabaseExtensions Class with a number of overloaded methods named CreateSprocAccessor<TResult>, ExecuteSprocAccessor<TResult>, CreateSqlStringAccessor<TResult>, ExecuteSqlStringAccessor<TResult>, etc.
Put succinctly, the Database Accessor Methods will perform data mapping for you to eliminate the need for the ContactFactory Class and looping through the IDataReader as shown above in the ContactsDAO Class. Because the methods return IEnumerable<TResult> you also have the ability to use LINQ To Objects on the results.
The best way to understand this is to rewrite the ContactsDAO FetchById Method to use the new Database Accessor Method, ExecuteSprocAccessor, in Enterprise Library 5:
public class ContactsDAO
{
private readonly Database _database;
public ContactsDAO(Database database)
{
_database = database;
}
public Contact FetchById(int id)
{
return _database.ExecuteSprocAccessor<Contact>
("FetchContactById", id).SingleOrDefault();
}
}
Notice that the looping through IDataReader and the data mapping between the IDataReader and Contact Class have been completely removed by a single call to ExecuteSprocAccessor<TResult> and a single LINQ Method, called SingleOrDefault. This is amazingly convenient!!!!
I will not go into this in detail at this time because this could easily change, but this code is assuming some conventions between the results returned by the IDataReader and the Contact Class. It assumes the names of the properties on Contact are the names of the columns for the IDataReader and it assumes that all columns are being returned by the stored procedure. If this is not the case, you can tell it differently by passing a different IRowMapper<TResult> into one of the overloaded methods, which we will save for another post.
Conclusion
That is just a taste of the Database Accessors in the Enterprise Library 5 Data Access Application Block. The DAAB is not trying to be a full-fledged O/R Mapper, like LINQ To SQL and Entity Framework. The new DatabaseExtensions Class and Database Accessors are trying to help you eliminate some of the repetitive code used with the DAAB when a developer wants to return classes and collections instead of ADO.NET objects into your .NET Applications.
I will talk about the Database Accessors in more detail in future posts. You can also watch for screencasts to appear on PnPGuidance tagged as Enterprise Library 5.
Hope this helps.
Part II: Database.ExecuteSqlStringAccessor and LINQ in Enterprise Library 5 DAAB

Comments