If you spend some time using Fluent NHibernate, you’ll want to use its neat style of mapping for all data access, even when you’re working against traditional DALs. I’ve put a sample up on MSDN Code Gallery for this scenario, using a fluent style of mapping between domain objects and data readers populated by stored procedure calls.
The interface is very similar to FNH, with a mapping class used for each domain entity – this is a simple mapping class:
public class PostCodeMap : DataReaderMap<PostCode>
{
public PostCodeMap()
{
Map(x => x.InwardCode, “PS_IN”);
Map(x => x.OutwardCode, “PS_OUT”);
}
}
The string constants define the column names expected in the data reader, and the base class takes care of running the map. For more complex entities, DataReaderMap also includes mapping via a conversion function:
Map<string, bool>(x => x.Activated, “AccountActivated”, Legacy.FromBoolean);
– where the mapping specifies to and from types, and a delegate to invoke for the conversion (in this case, a method which converts a legacy string representation of a boolean – Y/N – to a bool).
For composite objects, the base map includes referencing, for cases where the child entity is loaded from the same data reader as the parent entity:
References(x => x.Address, new AddressMap());
Where the child entity is read from a separate data reader, then the composition needs to be done outside of the map in a repository or an assembler component. The Load class isolates calling the stored procedure, so you get a fluent interface for populating domain objects, and collections of objects:
public User GetUser(Guid userId)
{
//populate basic details:
User user = Fluently.Load<User>().With<UserMap>()
.From<GetUser>(i => i.UserId = userId,
x => x.Execute());
//add accounts:
user.Accounts = Fluently.Load<List<Account>>().With<AccountMap>()
.From<GetUserAccounts>(i => i.UserId = userId,
x => x.Execute());
return user;
}
The From() call specifies the type of stored procedure, an action to populate the object, in this case setting up the UserId parameter, and a function to call which returns a data reader, in this case Execute().
The full sample is on the gallery here: Fluent DAL Mapping . It’s a simple task to extend the sample to load datasets, or to populate update procedure calls from entities. If your database is sufficiently conventional this could be extended to provide FNH-style auto-mapping, reflecting over entities and using conventions to map properties to column names.