In one of my current applications, I need to get customer data from a remote service (CRM) via Webservice / SOAP. But I also want to cache the data in the mysql database, so that I dont need to connect to the webservice for the next time (data does not change often, remote service is slow and has bandwidth limit - so caching is OK / a must).
I am quite sure about the technical part of this task, but I am not so sure about how to implement this clean and transparent in my web app.
All my other data comes from a single mysql database, so I repositories which return lists or single entities queried from the database with NHibernate.
My ideas so far:
1 all in one
Use a CustomerRepository, which looks for the customer by Id, if successfull, then return it, else call the webservice and save the retrieved data to the database.
Controller looks like this:
class Controller
{
private CustomerRepository Rep;
public ActionResult SomeAction(int id)
{
return Json(Rep.GetCustomerById(id));
}
}
Repository in pseudo / simple code like this:
class CustomerRepository
{
public Customer GetCustomerById(int id)
{
var cached = Database.FindByPK(id);
if(cached != null) return cached;
var webserviceData = Webservice.GetData(id);
var customer = ConvertDataToCustomer(webserviceData);
SaveCustomer(customer);
return customer;
}
}
Although the above looks somewhat straightforward, I think the CustomerRepository class will grow quite large and ugly. So I dont like that approach at all.
A repository should only load data from the database, that should be its "contract" in my app at least.
2 sepereate and sticked together in the controller
Use seperate classes for the repository (db access) and webservice (remote access) and let the controller do the work:
Controller looks like this:
class Controller
{
private CustomerRepository Rep;
private Webservice Service;
public ActionResult SomeAction(int id)
{
var customer = Rep.GetCustomerById(id);
if(customer != null) return Json(customer);
var remote = Service.GetCustomerById(id);
Rep.SaveCustomer(remote);
return Json(remote);
}
}
Although this looks a bit better, I still dont like to put all that logic in the controller, because error handling if the service does not return data is omitted and could probably clutter things a bit more.
Maybe I could make another service layer used by the Controller, but the code would be quite the same, but in another class.
Actually I would like to have my Controller use a single Interface/Class, which encapsulates that stuff, but I dont want one class which "does it all": accessing the repository, accessing the webservice, saving the data... it feels somewhat wrong to me...
All ideas so far are / will probably become quite bloated with caching code, error handling, etc. I think.
Maybe I could clean up a few things using AOP?
How would you implement stuff like the above?
Technical frameworks used: ASP.NET MVC, Spring.NET for DI, NHibernate as ORM, mysql as database, the remote service is accessed via SOAP.