Sunday, July 14, 2013

PetaPoco as it's meant to be; with repository and fluent mappings

When your domain objects get decorated with DataLayer column mappings, you create an unwanted dependency with your DayaLayer. To prevent this, you can create a mapping. This blog describes how I've done it. Comments are always welcome in the comment section below.

In the recently updated PetaPoco for Informix, I've created a FluentMapper. With this you can create a mapping of your domain object, without decorating them.

Here's how you can also benefit from this seperation. First create the domain object (DO):
public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Revenue { get;set; }
}
Followed by the mapper of the DO
public class CustomerMapper : FluentMapper<Customer>
{
    public CustomerMapper() : base("tblCustomer", "CustomerId")
    {
        this.Property(a=>a.Id, "CustomerId")
            .Property(a=>a.Name, "CustomerName")
            .Property(a=>a.Revenue, "Revenue", fromDbValue=>(int)fromDbValue / 10d, toDbValue => (int)((double)toDbValue * 10));
    }
}
Once the mapper is in place, we want to make sure we hook it up every time. This is why I make a DataContext class (which is used in the repository):
public class MyDataContext : Database
{
    //Because the PetaPoco.Mappers is static, we also hook up our mappers static
    static MyDataContext()
    {
        PetaPoco.Mappers.Register(typeof(Customer), new CustomerMapper());
    }
    public MyDataContext()
        : base(ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString))
    {
        
    }
}
Now we can create the repository for the customer related DataLayer functions (CRUD operations):
public class CustomerRepository
{
    private MyDataContext _dataContext
    public CustomerRepository(MyDataContext dataConext)
    {
        _dataContext = dataConext;
    }

    public Customer GetById(int customerId)
    {
        _dataContext.Get<Customer>(customerId);
    }

    public void Update(Customer customer)
    {
        _dataContext.Update(customer);
    }

    // etc
}
We can use it all together in the following way:
using(var dataContext = new MyDataContext())
{
    var customerRepository = new CustomerRepository(dataContext);
    var customer = customerRepository.GetById(1234);
}
As you can see the usage of the repository is super clean. Nobody knows where the data comes from, and nobody cares.

Let me know what you think of this solution!

Cheers,
Luuk