Uso del principio de separación de consulta de comandos en los controladores MVC

Me gusta la idea de Separación de consultas de comandos pero no puedo ver cómo usarlo dentro de una acción del controlador MVC que está agregando una entidad y necesita la ID de la nueva entidad después de agregarla.

Por ejemplo, en el ejemplo simplificado a continuación, se usa un servicio para crear un nuevo elemento:

public ActionResult Assign(AssignViewModel viewModel)
{
     var newItem = _AssignItemService.AssignItem(viewModel.ItemName, viewModel.ItemValue);

     return RedirectToAction("ListItem", new {id = newItem.Id);
}

Pero cuando redirijo a la acción que va a mostrar el nuevo elemento, necesito saber el ID del elemento recién creado para poder recuperarlo de la base de datos. Así que tengo que pedirle al servicio que devuelva el elemento recién creado (o al menos, su ID).

En CQS puro, un comando no tiene valor de retorno, por lo que el patrón anterior no sería válido.

Cualquier consejo recibido con gratitud.

preguntado el 03 de mayo de 12 a las 15:05

3 Respuestas

Creo que estás atascado en un punto pedante.

Una consulta es cuando desea hacerle una pregunta a la base de datos, como "¿Cuántos clientes al oeste del Mississippi compraron artículos de color rojo durante el mes de junio?" Esa es una consulta. Devolver el ID durante una inserción no es una consulta típica per se.

Como ocurre con la mayoría de las otras cosas en el desarrollo de software, este patrón no es un absoluto Incluso Fowler dice que está dispuesto a romperlo cuando sea conveniente hacerlo:

Reventar una pila es un buen ejemplo de un modificador que modifica el estado. Meyer dice correctamente que puede evitar tener este método, pero es un modismo útil. Así que prefiero seguir este principio cuando puedo, pero estoy preparado para romperlo para obtener mi pop.

Si realmente desea recuperar la identificación agregada más recientemente de una base de datos por separado de su inserción, puede usar algo como Identidad de alcance. Pero creo que está agregando complejidad sin ningún beneficio adicional.

contestado el 03 de mayo de 12 a las 16:05

Además, asegúrese de que, si usa la identidad de Scope o similar, maneje las situaciones de subprocesos múltiples correctamente. P.ej T1 inserciones, T2 inserciones, T1 se Id del T2insertar, T2 obtiene la misma identificación. Por supuesto, el mismo problema se aplica a cualquier operación/transacción atómica, así que estoy seguro de que lo ha considerado. - Básico

Otra buena razón para simplemente dejar que la base de datos le entregue el ID a través del valor de retorno de la función de inserción. - Robert Harvey

Creo que el comentario de Fowler tiene en cuenta que el método pop en una pila está bien, ya que su uso es general, por lo que se ha convertido en un modismo para todos los desarrolladores, pero no considero que devolver una identificación de un método save sea un modismo. Sin embargo, estoy de acuerdo contigo en que nada es absoluto y no es gran cosa romper este tipo de reglas de vez en cuando. jorgehmv

@jorgehmv: Sería un método de inserción, y devolver una ID de la base de datos es un modismo muy común y muy bien entendido. - Robert Harvey

@Robert, está bien, tal vez lo sea, pero también era un idioma bien entendido para devolver códigos de error de métodos hace muchos años, esta ya no es una buena práctica, martinfowler.com/refactoring/catalog/… - jorgehmv

deberías pasar a AssignItem método una instancia de "Elemento" (o cualquiera que sea el nombre de su entidad) que se crea a partir de los valores del modelo de vista, entonces el método no tiene que devolver nada, sino que simplemente actualizará la propiedad Id de la entidad convirtiéndolo en un método de Comando.

Luego puede usar la entidad. Id para lo que quiera

contestado el 03 de mayo de 12 a las 16:05

¿Cómo recuperas el "elemento" más tarde? - Robert Harvey

el objeto que se pasa al método AssignItem contiene la información de identificación una vez que se devuelve. Como el método es un comando, está bien cambiar el estado del objeto: jorgehmv

¿No estás básicamente devolviendo un valor en ese punto? Claro, no sale de la parte posterior de la función, pero aún está devolviendo un valor, simplemente está empujando el valor devuelto a otro lugar. Dicho esto, me gusta la idea de mantener el ID dentro del objeto, en lugar de devolverlo por separado. - Robert Harvey

Esa diferencia es la razón principal por la que la separación de consultas de comandos es una buena idea la mayor parte del tiempo. Si llama muchas veces al mismo método con los mismos argumentos, devolverá cosas diferentes cada vez, lo que es impar. En cambio, si pasa el mismo objeto una y otra vez, siempre no devolverá nada y solo cambiará el estado del objeto cuando sea necesario (generalmente solo la primera vez, ya que es una inserción de db) - jorgehmv

Nunca pasaría dos veces el mismo objeto para su inserción. Que el método devuelva algo diferente cada vez es por diseño; cada nuevo ID debe ser único para distinguirlo de los demás. - Robert Harvey

La forma de hacerlo sería hacer que la persona que llama especifique el ID de la nueva entidad (lo que probablemente implique el uso de GUID como clave).

Sin embargo, en mi experiencia, imponer la regla (purista) de que un comando no puede devolver un resultado va a causar problemas por poca ganancia.

contestado el 03 de mayo de 12 a las 16:05

Gracias erikallen. Tiene sentido, pero al final creo que la idea de jorgehmv me va a funcionar mejor. - Apetito

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.