2012-02-23 18 views
5

Estoy usando el patrón de repositorio donde tengo una clase de repositorio por tabla de base de datos. Me preguntaba cómo ustedes se acercan a las consultas que sólo tienen que devolver un número específico de columnasPatrón de repositorio y tipos de devolución

Por ejemplo decir que tienen la siguiente

Tabla de artículos (tabla ficticia)

ItemId 
Name 
PurchaseDate 
Description 
Price 

En mi código: creo un objeto con los campos anteriores llamados Item.cs (actualmente no usa un orm).

Si tengo varios escenarios en los que necesito para volver

  1. ItemId
  2. Una combinación de purchaseDate y Nombre
  3. ItemId y precio

que sería el mejor enfoque?

  1. Obtener todos los campos de la tabla de artículos y devolver un objeto Artículo (consulta 1 repo)
  2. crear tres consultas en Repo y devolver un objeto del artículo para cada una
  3. Cree tres consultas en Repo y devolver sólo ¿Qué se necesita?

Ahora imagina este escenario con una tabla con más de 10 campos.

Personalmente, me gusta la opción uno, pero no estoy seguro de si hay una mejor manera de hacerlo.

Respuesta

6

yo personalmente utilizar un repositorio de tipo genérico y leer y tener mi AsQueryable()

Esta es la unión.

interface IRepository<T> 
{ 
    void Create(T item); 
    IQueryable<T> Retrieve(); 
    void Update(T item); 
    void Delete(T item); 
    void SubmitChanges(); 
} 

y aquí está la implementación.

public class PersonsRepository : IRepository<Person> 
{ 
    private DataContext dc; 

    public PersonsRepository(DataContext dataContext) 
    { 
     dc = dataContext; 
    } 

    public void Create(Person Person) 
    { 
     dc.Persons.Add(Person); 
    } 

    public IQueryable<Person> Retrieve() 
    { 
     IQueryable<Person> Person = (from s in dc.Persons 
             select s); 
     return Person.AsQueryable(); 

    } 

    public void Update(Person Person) 
    { 
     Person _Person = (from s in dc.Persons 
          where s.ID == Person.ID 
          select s).Single(); 
     { 
      _Person.LastLogin = Person.LastLogin; 
      _Person.Password = Person.Password; 
      _Person.LastUpdate = Person.LastUpdate; 
      // Cannot change your username. 
     } 
    } 

    public void Delete(Person Person) 
    { 
     dc.Persons.Remove(Person); 
    } 

    public void SubmitChanges() 
    { 
     dc.SaveChanges(); 
    } 
} 

Ahora, si necesita consultar el repositorio, desea hacer algo como esto.
perdóname, el código de abajo no se ha probado y estoy en realidad más de un tipo VB :(
esperamos que pueda obtener el punto

public class PersonsService 
{ 
    private PersonRepository<Person> personRepository; 

    public PersonService() 
    { 
     personRepository = new PersonRepository<Person>(); 
    } 

    public UsablePerson GetPersonByID(int ID) 
    { 
     UsablePerson person = (from p in personRepository<Person>.Retrieve 
           where p.ID = ID 
           select new UsablePerson { p.FirstName, 
                 p.LastName, 
                 p.EmailAddress }).FirstOrDefault(); 

     return person; 
    } 
} 

Para mis propósitos, estoy usando LINQ sobre este particular proyecto, pero esto se puede adaptar a la capa de datos que desee ... esa es la belleza de una capa de repositorio.

Desde aquí, "personalmente" también tengo una capa de servicio que trata los matices de la conexión de datos ... cosas como GetPersonByID o GetPeopleSince(DateTime marker). Aquí es donde elimino la información que no necesito (IE: contraseñas) y almacena la información restante en un ViewModel u otro POCO.

+0

Solo para ver si estoy en la misma página. Para consultas más específicas como (GetPersonByID), devuelve el registro de persona completo del Repo y luego, en la capa de servicio, elimina toda la información innecesaria y devuelve solo la ID. Podría mostrar un ejemplo de esto, porque esto es con lo que estoy teniendo dificultades. No estoy seguro de si debería crear mucho método Repo o simplemente tener uno que siempre devuelva todas las columnas de la tabla (es decir, toda la fila) – chobo

+0

Hice lo mejor que pude de memoria ... No tengo mi IDE frente a mí así que probablemente haya algunos errores en el ejemplo anterior. Espero que entiendas la imagen. –

+0

Me gusta esa técnica porque reduce el número de métodos en los repositorios. Pero, siempre me enseñaron que solo debe devolver las columnas que necesita de una base de datos, parece que con un Repositorio siempre está devolviendo un tipo de entidad o colección de entidades. ¿Es ésa la intención del patrón Repositorio? Tal vez estoy pensando que el impacto en el rendimiento de la base de datos – chobo

0

Me gustan los repositorios basados ​​en Linq para este tipo de cosas.Linq2SQL, MSEF o Linq2NH le permitirían, a través del método Select(), definir su lista de columnas. A continuación, recibiría un objeto de dominio o una clase de entidad rellenada solo con lo que haya especificado. Puede tener un código adicional para asignarlo a un DTO, o simplemente usar la clase de dominio sabiendo que no estaba completamente "hidratado".

2

Si piensa en Domain Driven Design, el hecho de que un solo objeto tenga una configuración diferente probablemente indique diferentes dominios. Esto no requiere un objeto diferente para cada uno, pero es un buen patrón. Una forma de lograr esto es tener una clase base con el conjunto minimalista de propiedades. A continuación, crea más clases "específicas de dominio" que heredan de la base.

En cuanto a la devolución de datos, hay una variedad de formas de "controlar el tráfico" del flujo. Múltiples repositorios separan los dominios muy bien, por ejemplo. Pero esto agrega complejidad (no es una buena idea a menos que sea absolutamente necesario). No me gusta un único repositorio que devuelva diferentes objetos. Es más aceptable si tiene algunas propiedades que aceptan nulos (tal vez).

No me gusta LINQ to SQL como DAL, como ha sugerido @KethiS, pero trabajo en un entorno empresarial y LINQ to SQL básicamente apesta a escala. Usar LINQ de lo contrario es genial. Solo mis dos centavos.

Si puede devolver un tipo de objeto, es mejor. Si la diferencia en los objetos se basa en permisos, considere borrar los datos que el usuario no debería ver. Sin embargo, tenga en cuenta que esto no es tan escalable si toma una gran cantidad de objetos.

+0

+1 buena respuesta. – jgauffin

+1

Tiendo solo a devolver un tipo de objeto del repositorio, pero lo que me molesta es si siempre devuelvo un objeto Entity? Por ejemplo, si tengo un método llamado GetEmployeeID, ¿debería devolver un objeto Employee con solo ese campo? ¿O debería devolver solo un número de empleado? ¿Debo simplemente utilizar un método getEmployee o debería dividirlos en métodos más específicos en Repo como GetEmployeeId vs siempre usando GetEmployee? – chobo

5

Agrego métodos a mis repositorios cuando los necesito en contraste con repositorios genéricos donde obtiene un conjunto de métodos sin importar si los necesita o no.

De vuelta IQueryable es una abstracción que gotea.

Eche un vistazo a Domain Driven Design (el libro) y obtendrá una buena idea de cómo deberían ser los repositorios bien diseñados.

También he escrito una queja sobre repositorios genéricos: http://blog.gauffin.org/2012/02/generic-repositories-a-silly-abstraction-layer/

+0

De acuerdo, devolver un 'IQueryable' hace bastante bien lo contrario de lo que quiere que haga un repositorio, es solo que se trata de un problema de infraestructura directamente en su capa de dominio. – davenewza

0

¿Por qué le devolverá todos los campos cuando realmente se necesita sólo unos pocos de ellos? Seleccione los campos que realmente desea si le preocupa el rendimiento. No soy un gran admirador de seguir estrictamente un patrón de diseño, tal vez deberías considerar modificar el diseño de acuerdo a tus requerimientos.

Cuestiones relacionadas