none
Duda con el patrón repositorio RRS feed

  • Pregunta

  • Hola.

    Hago una aplicación en MVC utilizando C# y mi duda es respecto al patrón repositorio, tengo cinco clases que representan a 5 tablas de mi base de datos, quiero implementar el patrón repositorio y buscando en internet encontré este ejemplo en una pagina x

    Mi pregunta es: tendré que crear cinco clases(por las cinco clases en mi modelo) que me implementen la interfaz IRepository? esa es la manera correcta de trabajar con el patrón repositorio? 


    pabletoreto

    miércoles, 7 de enero de 2015 15:10

Respuestas

  • Básicamente, yo diría que sí.  Podría tratar de darle vueltas al asunto y tratar de manejar un único repositorio, pero la verdad es que no todas las entidades siempre tienen lo mismo, y aún si creara un repositorio que devuelva un objeto sin tipo particular como un Data Transfer Object, pierde la seguridad que le da devolver el tipo de datos correcto y pierde la habilidad de crear métodos en repositorios más especializados.

    Por ejemplo, imagínese un repositorio de strings por idioma.  En base de datos se tiene la tabla tblStrings con los campos ID (autonumérico y clave primaria), StringId y LangId.  Los dos últimos son un UNIQUE INDEX.  La idea de la tabla es tener el contenido de una base de datos traducido a múltiples idiomas para presentarlo en una interfase gráfica usada internacionalmente.  La idea es NO buscar por ID un texto particular, la idea es buscar por stringId y LangId según la preferencia de idioma del usuario.  Si tuviera una única interfase para todos los repositorios, no podría crear un método Get(int stringId, string langId) para el repositorio específico de los textos traducidos.

    Así que tarde o temprano tendría que hacer la distinción.  Si no hace la distinción en el repositorio, tendrá que hacerla en otra parte.  Pero como todo, son pocas las cosas "escritas en piedra".  Experimente y determine usted mismo qué es lo que mejor le sirve.


    Jose R. MCP
    Code Samples

    • Marcado como respuesta pabletoreto miércoles, 7 de enero de 2015 15:56
    miércoles, 7 de enero de 2015 15:29
    Moderador
  • >>sino solo debo hacer esto: public class Orders: IRepository<Orders>, IRepository<Employee>, IRepository<Customers>  ?

    no, no las clases concretas debes crearlas, salvo que definsa una clase base

    public class RepositoryBase<T> ; IRepository<T>{
    
       //implementacion de la interface
    
    }


    una cosa es la definicion de la interfaz y otra la implementacion

    en tu pregunta apuntabas a la definicion de la interfaz no de la clase concreta

    si vas a tener una clase base puedes aplciar la misma regla solo definir una implementacion concreta si es que se extiende la funcionalidad

    sino lo hace con solo definir RepositoryBase<Ordenes>, RepositoryBase<Employee> alcanza y si se extiende usarias

    public class CommentRepository : RepositoryBase<Post>, ICommentRepository {
    
          //implementas metodos ICommentRepository
    }

    alli si creas una clase concreta que hereda de la clase base

    remarco que alli estarias definiendo interfaces y clases base, esta ultima es la que implementa funcionalidad comun para todas las clases

    para usarla seria tan simple como hacer

    var employeeRepo = new RepositoryBase<Employee>();
    
    var listemployee = employeeRepo.GetAll();


    sin ninguna otra clase que definir

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta pabletoreto miércoles, 7 de enero de 2015 15:56
    miércoles, 7 de enero de 2015 15:44

Todas las respuestas

  • >>tendré que crear cinco clases(por las cinco clases en mi modelo) que me implementen la interfaz IRepository?

    no es necesario si es que esa clase no va a extender la funcionalidad base de la interfaz

    por ejemplo si en Comment necesitas algun metodo como ser GetByUser() entonces podrias definir

    public interface ICommantRepository : IRepoistory<Comment>{
    
       List<Comment> GetByUser(int iduser);
    
    }


    pero sino necesitas agregar nada adicional no hace falta que la definas

    public class PostRepository : IRepository<Post>{
    
       //implementas metodos IRepository
    
    }
    
    public class CommentRepository : IRepository<Post>, ICommentRepository{
    
         //implementas metodos IRepository
    
          //implementas metodos ICommentRepository
    }


    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina


    miércoles, 7 de enero de 2015 15:27
  • Básicamente, yo diría que sí.  Podría tratar de darle vueltas al asunto y tratar de manejar un único repositorio, pero la verdad es que no todas las entidades siempre tienen lo mismo, y aún si creara un repositorio que devuelva un objeto sin tipo particular como un Data Transfer Object, pierde la seguridad que le da devolver el tipo de datos correcto y pierde la habilidad de crear métodos en repositorios más especializados.

    Por ejemplo, imagínese un repositorio de strings por idioma.  En base de datos se tiene la tabla tblStrings con los campos ID (autonumérico y clave primaria), StringId y LangId.  Los dos últimos son un UNIQUE INDEX.  La idea de la tabla es tener el contenido de una base de datos traducido a múltiples idiomas para presentarlo en una interfase gráfica usada internacionalmente.  La idea es NO buscar por ID un texto particular, la idea es buscar por stringId y LangId según la preferencia de idioma del usuario.  Si tuviera una única interfase para todos los repositorios, no podría crear un método Get(int stringId, string langId) para el repositorio específico de los textos traducidos.

    Así que tarde o temprano tendría que hacer la distinción.  Si no hace la distinción en el repositorio, tendrá que hacerla en otra parte.  Pero como todo, son pocas las cosas "escritas en piedra".  Experimente y determine usted mismo qué es lo que mejor le sirve.


    Jose R. MCP
    Code Samples

    • Marcado como respuesta pabletoreto miércoles, 7 de enero de 2015 15:56
    miércoles, 7 de enero de 2015 15:29
    Moderador
  • >>tendré que crear cinco clases(por las cinco clases en mi modelo) que me implementen la interfaz IRepository?

    no es necesario si es que esa clase no va a extender la funcionalidad base de la interfaz

    por ejemplo si en Comment necesitas algun metodo como ser GetByUser() entonces si usarias

    public interface ICommantRepository : IRepoistory<Comment>{

       List<Comment> GetByUser(int iduser);

    }

    pero sino necesitas agregar nada adicional no hace falta que la definas

    public class PostRepository : IRepository<Post>{
    
       //implementas metodos IRepository
    
    }
    
    public class CommentRepository : IRepository<Post>, ICommentRepository{
    
         //implementas metodos IRepository
    
          //implementas metodos ICommentRepository
    }


    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    Gracias Leandro, aun me confundo con algunos conceptos, dejame poner tu respuesta en mis palabras y tu me haces el favor de decirme si entendi bien:

    entonces si tengo por ejemplo tres clases(Employee, Orders y Customers) no necesito hacer una case employee que me implemente la interfaz IRepository, otra clase Orders que me implemnete la interfaz IRepository y una ultima clase Customers.cs que me implemente IRepository, sino solo debo hacer esto:

    public class Orders: IRepository<Orders>, IRepository<Employee>, IRepository<Customers>  ?


    pabletoreto

    miércoles, 7 de enero de 2015 15:36
  • Básicamente, yo diría que sí.  Podría tratar de darle vueltas al asunto y tratar de manejar un único repositorio, pero la verdad es que no todas las entidades siempre tienen lo mismo, y aún si creara un repositorio que devuelva un objeto sin tipo particular como un Data Transfer Object, pierde la seguridad que le da devolver el tipo de datos correcto y pierde la habilidad de crear métodos en repositorios más especializados.

    Por ejemplo, imagínese un repositorio de strings por idioma.  En base de datos se tiene la tabla tblStrings con los campos ID (autonumérico y clave primaria), StringId y LangId.  Los dos últimos son un UNIQUE INDEX.  La idea de la tabla es tener el contenido de una base de datos traducido a múltiples idiomas para presentarlo en una interfase gráfica usada internacionalmente.  La idea es NO buscar por ID un texto particular, la idea es buscar por stringId y LangId según la preferencia de idioma del usuario.  Si tuviera una única interfase para todos los repositorios, no podría crear un método Get(int stringId, string langId) para el repositorio específico de los textos traducidos.

    Así que tarde o temprano tendría que hacer la distinción.  Si no hace la distinción en el repositorio, tendrá que hacerla en otra parte.  Pero como todo, son pocas las cosas "escritas en piedra".  Experimente y determine usted mismo qué es lo que mejor le sirve.


    Jose R. MCP
    Code Samples

    Gracias Jose, crei que habia una manera "general" de hacerlo.

    pabletoreto

    miércoles, 7 de enero de 2015 15:40
  • >>sino solo debo hacer esto: public class Orders: IRepository<Orders>, IRepository<Employee>, IRepository<Customers>  ?

    no, no las clases concretas debes crearlas, salvo que definsa una clase base

    public class RepositoryBase<T> ; IRepository<T>{
    
       //implementacion de la interface
    
    }


    una cosa es la definicion de la interfaz y otra la implementacion

    en tu pregunta apuntabas a la definicion de la interfaz no de la clase concreta

    si vas a tener una clase base puedes aplciar la misma regla solo definir una implementacion concreta si es que se extiende la funcionalidad

    sino lo hace con solo definir RepositoryBase<Ordenes>, RepositoryBase<Employee> alcanza y si se extiende usarias

    public class CommentRepository : RepositoryBase<Post>, ICommentRepository {
    
          //implementas metodos ICommentRepository
    }

    alli si creas una clase concreta que hereda de la clase base

    remarco que alli estarias definiendo interfaces y clases base, esta ultima es la que implementa funcionalidad comun para todas las clases

    para usarla seria tan simple como hacer

    var employeeRepo = new RepositoryBase<Employee>();
    
    var listemployee = employeeRepo.GetAll();


    sin ninguna otra clase que definir

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    • Marcado como respuesta pabletoreto miércoles, 7 de enero de 2015 15:56
    miércoles, 7 de enero de 2015 15:44