Linq To SQL y Repository Pattern… sí, pero ojo!

Hola a todos! Hoy, por temas que no vienen al caso, estaba mirando el tutorial de MVC que hay en asp.net. Hay dos apartados dedicados a explicar como se pueden realizar modelos usando Linq to Sql y EF. Hasta ahí, ningún problema.

El problema viene, cuando en el apartado dedicado a Linq to Sql, una vez han dado un ejemplo de uso de las clases de Linq to Sql desde un controlador, dicen que esta solución, aunque correcta, implica que si en un futuro cambiamos el proveedor de acceso a datos vamos a tener que tocar todos nuestros controladores, ya que usamos las clases Linq to Sql desde ellos. También se menciona que el uso del patrón Repositorio (repository pattern) nos permite aislarnos de Linq to Sql de modo que si más adelante migramos, digamos a EF, no tengamos que modificar nuestros controladores.

Cuando usamos Linq to Sql se nos generan por un lado una clase que hereda de DataContext y que representa nuestra base de datos, y por otro un conjunto de clases que representan a nuestras tablas (nuestros datos). Esas clases no son POCO y están generadas y controladas por Linq to Sql.

Esta es el ejemplo que proporcionan en asp.net sobre el uso del patrón repositorio:

namespace MvcApplication1.Models
{
public class MovieRepository : IMovieRepository
{
private MovieDataContext _dataContext;

public MovieRepository()
{
_dataContext = new MovieDataContext();
}
public IList<Movie> ListAll()
{
var movies = from m in _dataContext.Movies
select m;
return movies.ToList();
}
}
}

El repositorio MovieRepository es quien nos da acceso a los datos contenidos en la base de datos y nos independiza de la clase Linq to Sql MovieDataContext. ¡Bien!

El ejemplo de uso que proporcionan desde un controlador es el siguiente:

public class MoviesController : Controller
{
private IMovieRepository _repository;
public MoviesController(IMovieRepository repository)
{
_repository = repository;
}
public ActionResult Index()
{
return View(_repository.ListAll());
}
}

Aprovechan además para comentarnos que el parámetro repository del constructor podría esta inyectado por un contenedor IoC (con lo que estoy totalmente de acuerdo). Luego nos enfatizan de que la dependencia de este controlador es solamente con IMovieRepository, con lo que por un lado podemos pasar un Mock de IMovieRepository cuando usamos tests unitarios y por otro si algún dia migramos a EF, nos basta con crear un EFMovieRepository y… listos.

Pues no.

Veis el problema? No? Y si cambio el código del método Index() por el siguiente código equivalente?

 public ActionResult Index()
{
IList<Movie> movies = _repository.ListAll();
return View(movies);
}

Detectais ahora el problema? El controlador MoviesController no depende de MovieDataContext, de acuerdo, pero sigue dependiendo de las clases generadas por Linq-to-Sql (en este caso de la clase Movie). Con el ejemplo que hay en asp.net tal y como está, de poco nos sirve implementar el patrón repositorio: cuando migremos a otro proveedor de datos (pongamos EF) vamos a tener que tocar igualmente todos los controladores.

Hay solución para el problema? Como (casi) todo en esta vida tiene solución, pues si que la hay: podemos forzar a Linq to SQL a que utilice clases POCO aunque perdemos algunas de sus capacidades (y por lo que he visto tampoco es que sea trivial). Existe una buena explicación al respecto en http://blogs.msdn.com/digital_ruminations/archive/2007/08/28/linq-to-sql-poco-support.aspx.

Si buscais “Repository Pattern” “Linq to Sql” en google encontrareis interesantes discusiones y posibles implementaciones al respecto, pero el objetivo de mi post no era tanto ofrecer soluciones al problema, si no hacer notar el pequeño problema en el ejemplo de asp.net y que, como siempre, no debemos creernos directamente todo lo que vemos.

Un saludo!

Un comentario sobre “Linq To SQL y Repository Pattern… sí, pero ojo!”

  1. Gracias por el aporte, actualmente estoy trabajando en nuevo estandar para mis aplicaciones, antes tenía una clase por cada tabla y hacia llamados utilizando SqlHelper a los procedimientos de insertar, actualizar, etc. ahora supongo que puedo utilizar este asunto del datacontext como mi capa de acceso a datos y crear mis entidades igual que siempre. Voy a realizar las búsquedas que sugieres a ver qué encuentro.

    gracias nuevamente.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *