7

Tengo dificultades para entender cómo consultar mejor un repositorio.repositorios y consultas con sql en bruto?

Los tres factores que me están tirando a través de un bucle en este momento son: Tipo de

  1. Retorno de los datos
  2. Columnas para ejecutar la consulta en
  3. Número de registros para volver

Punto 1

En lo que respecta a la búsqueda ion one:

Tengo repositorios con muchos métodos que devuelven una combinación de Entidades y valores escalares. Esto parece conducir a la "explosión de método". ¿Debo devolver siempre un objeto Entity? ¿Cómo debo consultar los objetos donde solo necesito una columna?

Punto 2 Al ejecutar una consulta, ¿debo incluir todas las columnas en la tabla, incluso si solo necesito una, o dos columnas? Si creo consultas específicas para esto conduce a más métodos en el Repositorio

Punto 3 ¿Cómo debería proporcionar las condiciones para la consulta? Leí sobre Especificaciones, pero entiendo que recorre los registros devueltos y filtra los que pasan a una nueva colección. Esto no parece una buena idea para el rendimiento. Ahora mismo solo hago un método nuevo en Repo como getNameById() que encapsula la condición.

Por favor, no es que no estoy usando un ORM, solo tengo raw sql en mis repositorios.

actualización

Punto 1: Sobre la base de las respuestas y un poco más investigación sería esto una buena implementación?

Ahora tengo un gran repositorio que devuelve una mezcla de objetos de tipo escalar y entidad (la misma entidad). Estoy pensando que podría reducirlo mucho si solo utilizo un método GetUser (userId) y olvido los métodos de escritura que solo devuelven valores de columna individual.

Por ejemplo, si necesito devolver un nombre de usuario, podría llamar al método GetUser (userId) que hidrata el objeto User y luego en la capa de servicio simplemente filtrarlo al nombre de usuario.

Otra forma sería utilizar algún tipo de clase QueryBuilder que podría pasar al Repositorio que podría ser analizado para generar el sql adecuado.

Punto 2

Mirando hacia atrás esto es bastante similar al punto uno y mi solución actual sería que la puede llevar todos los campos de la tabla. Es una compensación entre el rendimiento y la capacidad de mantenimiento.

Punto 3

que tendría que proporcionar algún tipo de cláusula where. No estoy seguro si esto tiene sentido al hacer una especificación o solo una cadena sql. Mi solución actual es hacer nuevos métodos para estos tipos, pero me gustaría algo más genérico para el Repositorio

En general, sigo investigando sobre esto ... Me encantaría escuchar más información sobre esto o enlaces a libros o referencias que tipo de atar todo esto juntos.

+0

¿Crees el comando Sql dinámicamente en tu clase? – Arian

+0

SQL sin procesar y sin ORM, ¿ja? Como vivir al límite, ¿verdad? En serio, ¿por qué quieres tratar con raw sql? –

+0

@yves - pasos de bebé :) – chobo

Respuesta

3

Tengo Repositorios con muchos métodos que devuelven una combinación de Entidades y valores escalares. Esto parece conducir a la "explosión de método". ¿Debo devolver siempre un objeto Entity? ¿Cómo debo consultar los objetos donde solo necesito una columna?

Puede luchar contra el método de depósito de depósito de forma similar a como lucharía contra otras violaciones de SRP. Puede crear otro repositorio para la misma entidad. Vea esto answer a una pregunta similar.

Al ejecutar una consulta ¿debo incluir todas las columnas en la tabla, incluso si solo necesito una, o dos columnas? Si creo consultas específicas para esto, esto conduce a más métodos en el Repositorio

Esta no es una pregunta DDD. El diseño impulsado del dominio no se ocupa de 'filas y columnas'. Siempre hay cierta redundancia en la cantidad de datos que carga para 'hidratar' el objeto de dominio, pero debe medir si esto realmente afecta su rendimiento. Si esto es realmente un cuello de botella de rendimiento que puede ser un síntoma de modelo de dominio incorrecto.

¿Cómo debo proporcionar condiciones para la consulta? Leí sobre Especificaciones, pero entiendo que recorre los registros devueltos y filtra los que pasan a una nueva colección. Esto no parece una buena idea para el rendimiento. Ahora mismo solo hago un método nuevo en Repo como getNameById() que encapsula la condición.

Esto de nuevo es un problema de acceso a los datos. Nada en DDD dice que su repositorio no puede convertir la especificación a una consulta SQL. Depende de usted si hace esto o itera sobre los registros en la memoria (siempre que el consumidor del repositorio solo vea Especificación y Repositorio y permanezca inconsciente de la implementación real).

En cuanto a 'SQL sin formato frente a ORM en DDD', puede encontrar este answer interesante.

+0

¿Podría indicar algunas respuestas o tutoriales que abordan este problema de acceso a los datos? – chobo

+0

El libro DDD tiene un ejemplo sobre la especificación que se convierte en SQL sin procesar debido a consideraciones de rendimiento. – Dmitry

+0

¿Es ese el azul de Eric Evans? ¿No sabría el número de página de ese ejemplo?:) – chobo

1

Antes que nada, realmente no ha explicado para qué está utilizando todas estas consultas. Es probable que se deba a las necesidades de la interfaz del usuario. Si es así, no hay necesidad de pasar por todos estos aros (servicio-> repositorio-> dominio-> dto-> cliente), solo consulte la base de datos lo más directamente posible. Y lo que usted sabe, ya no están las preguntas sobre si puede consultar escalas o solo las columnas que necesita. Simplemente use sql simple y devuelva lo que necesita. No crees abstracciones que causen fricción.

+0

Todo lo que estoy buscando es un enfoque de "mejores prácticas" para consultar repositorios, así que no tengo un millón de métodos y de alguna manera factores en algún rendimiento decente también. – chobo

+0

Comience por no agregarlos al repositorio en primer lugar si no cumplen la función del dominio. Muévalos a otra fachada que represente las consultas que necesita la interfaz de usuario. Vaya tan rápido de cliente a fachada a db a fachada a cliente. Use DTO simples para representar el estado que necesita transportarse al cliente. –

2

Estoy de acuerdo con todo lo que dice Dmitry, pero quizás piense que debería leer CQRS.

Solía ​​hacer preguntas similares al comenzar con DDD (con respecto a 'explosión de método', no a sus problemas de SQL), y esto me llevó a CQRS.Personalmente, realmente no veo cómo DDD es práctico sin él, y responde muchas de estas preguntas cuando se trata de consultar datos. Usando sus principios, lo que sugeriría es:

  1. Solo use repositorios de dominio al realizar una transacción. Es decir, no usa repositorios para mostrar datos en la interfaz de usuario. Solo obtiene agregados de su repositorio cuando desea realizar una operación en su contra.
  2. Sus repositorios solo devuelven agregados, no entidades individuales por separado. Esto tiene sentido ahora ya que solo estamos usando repositorios en un sentido transaccional, y las entidades solo pueden ser mutadas a través de operaciones atómicas y persistidas por el agregado como un todo.
  3. Crea repositorios separados (o 'servicios de consulta') que proporcionan consultas personalizadas y tipos de datos para cualquier dato que necesite. Estos pueden devolver tontos DTOs sin lógica.

Esto mantiene su dominio propio & repositorios limpia, al tiempo que proporciona los medios para crear una delgada capa de acceso de datos que proporciona consultas de alto rendimiento.

Respecto del patrón de especificación: en lugar de convertirlo en una consulta SQL en código, puede proporcionar propiedades públicas en la especificación que representa los criterios. Estos valores podrían luego agregarse en la cláusula where de su SQL o enviarse como parámetros a un SPROC.

1

Chobo,

Tenemos que recordar dos cosas acerca de Repositorio patrón [Fowler PoEAA] [Evans DDD]:

  1. utilizar un patrón de repositorio como una colección sencilla. El repositorio resume estos detalles de infraestructura porque no provienen del dominio.
  2. Si un repositorio pattren es una colección, es un grupo de objetos del mismo tipo.

Otros dos tipos pueden ayudar a su repositorio: los patrones Query Object [Fowler PoEAA] y Data Mapper [Fowler PoEAA]. Criterios de agregado de patrón de objeto de consulta utilizando métodos orientados a objetos y saber cómo traducirlos como una declaración de SQL. El patrón de Data Mapper sabe mapear los estados del objeto de la aplicación y las columnas de la tabla de las bases de datos.

Puede usar el patrón de carga diferida [Fowler PoEAA] para mitigar el problema de objetos grandes en la memoria.

¡Éxito para usted!

+0

Creo que el objeto de consulta ayudaría mucho con el problema de consultar con diferentes criterios. Supongo que los ORM tienen esto incorporado. ¡Gracias por la lista de patrones que abordan estos problemas! – chobo