Antecedentes:
estoy diseñando una aplicación de servidor y creando dll separados para diferentes subsistemas. Para simplificar las cosas, digamos que tengo dos subsistemas: 1) Users
2)Projects
La interfaz pública de los usuarios tiene un método como:
IEnumerable<User> GetUser(int id);
Y la interfaz pública de Proyectos tiene un método como:
IEnumerable<User> GetProjectUsers(int projectId);
Entonces, por ejemplo, cuando necesitamos mostrar a los usuarios para un determinado proyecto, podemos llamar GetProjectUsers
y eso devolverá objetos con información suficiente para mostrar en una cuadrícula de datos o similar.
Problema:
Idealmente, el Projects
subsistema no debería también almacenar información del usuario y solo debería almacenar los ID de los usuarios que participan en un proyecto. Para servir GetProjectUsers
, necesita llamar GetUser
al Users
sistema para cada ID de usuario almacenado en su propia base de datos. Sin embargo, esto requiere muchas GetUser
llamadas separadas , lo que genera muchas consultas sql separadas dentro del User
subsistema. Realmente no he probado esto, pero tener este diseño hablador afectará la escalabilidad del sistema.
Si dejo de lado la separación de los subsistemas, podría almacenar toda la información en un solo esquema accesible por ambos sistemas y Projects
podría simplemente hacer una JOIN
para obtener todos los usuarios del proyecto en una sola consulta. Projects
también necesitaría saber cómo generar User
objetos a partir de los resultados de la consulta. Pero esto rompe la separación que tiene muchas ventajas.
Pregunta:
¿Alguien puede sugerir una forma de mantener la separación mientras se evitan todas estas GetUser
llamadas individuales durante GetProjectUsers
?
Por ejemplo, una idea que tuve fue que los usuarios deberían dar a los sistemas externos la capacidad de "etiquetar" a los usuarios con un par de valor de etiqueta y solicitar a los usuarios con un cierto valor, por ejemplo:
void AddUserTag(int userId, string tag, string value);
IEnumerable<User> GetUsersByTag(string tag, string value);
Luego, el sistema Proyectos podría etiquetar a cada usuario a medida que se agregan al proyecto:
AddUserTag(userId,"project id", myProjectId.ToString());
y durante GetProjectUsers, podría solicitar a todos los usuarios del proyecto en una sola llamada:
var projectUsers = usersService.GetUsersByTag("project id", myProjectId.ToString());
la parte de la que no estoy seguro es: sí, los usuarios son agnósticos de los proyectos, pero realmente la información sobre la membresía del proyecto se almacena en el sistema de los usuarios, no en los proyectos. Simplemente no me siento natural, así que estoy tratando de determinar si hay una gran desventaja aquí que me estoy perdiendo.
fuente
GetUser
lugar de consultar la base de datos, buscará en la memoria caché. Esto significa que en realidad no importa cuántas veces llameGetUser
, ya que cargará datos de la memoria en lugar de la base de datos (a menos que la memoria caché se haya invalidado).select
consultas por día, será mejor que use el almacenamiento en caché. Por otro lado, si está agregando miles de millones de entidades a una base de datos pero solo obtiene unos pocos miles deselect
s con s muy selectivoswhere
, el almacenamiento en caché puede no ser tan útil.