¿Puedo resolver con nhibernate esto o es un error en mi modelo?

6 views
Skip to first unread message

Roberto Ramírez

unread,
Feb 15, 2010, 1:11:52 PM2/15/10
to NHibernate-Hispano
Buenos días a todos.

¿Puedo resolver con nhibernate esto o es un error en mi modelo?

Yo guardo una factura con su respectivo detalle, dentro de mi modelo
yo necesito generar un movimiento en inventario y por cada movimiento
guardar la referencia del detalle de la factura así:

Factura ==> Detalle ==> Movimiento

El proceso del movimiento al inventario es un paso intermedio al
momento de guardar-actualizar mi factura.

En mi modelo, el detalle de la factura no conoce los movimientos en el
inventario, pero el movimiento si conoce a que detalle de factura
pertenece.

¿Como identificar la referencia del detalle para insertarla en el
movimiento si todo se ejecuta en un solo request (Session-Per-Request)
y aun no conozco la referencia del detalle que se guardo en la base de
datos?

Uso Visitor como patron de diseño tomado del post de J. Rommaniello
http://jfromaniello.blogspot.com/2009/11/caso-practico-patron-visitor.html,
el proceso del movimiento lo realizo en un Visitor.

Muchas gracias por su ayuda.

Gustavo Ringel

unread,
Feb 15, 2010, 1:51:07 PM2/15/10
to nhibernat...@googlegroups.com
No entiendo exactamente donde entra NH en la consullta.
Es decir, el codigo que yo pienso para resolver eso al menos es independiente de la capa de persistencia, tambien los visitors  de Jose son independientes de la capa de persistencia.

Creo que NH no es un factor para la decision de negocio. Podrias transformarlo en un factor si quisieras usar Listeners o alguna cosa especifica de NH para guardar el movimiento.

En mi caso el servicio que guarda la factura y los detalles llama al Dao/Repositorio que sabe guardar una factura y sus detalles y se genera un evento de dominio para cada detalle de factura.

Otro componente recibe esos eventos y se encarga de guardar los movimientos.

Los visitors de Jose hacen algo parecido a eso, pero creo que tambien Jose para esos casos  favorece domain events hoy en dia :)

Gustavo.

2010/2/15 Roberto Ramírez <jramir...@gmail.com>

--
Para escribir al Grupo, hágalo a esta dirección: NHibernat...@googlegroups.com
Para más, visite: http://groups.google.com/group/NHibernate-Hispano

Roberto Ramírez

unread,
Feb 15, 2010, 1:59:18 PM2/15/10
to NHibernate-Hispano
Muchas gracias por la respuesta Gustavo, me queda claro lo que
comentas.

Una cuestión pequeñita... ¿un evento de dominio == listeners de nh?

On 15 feb, 10:51, Gustavo Ringel <gustavo.rin...@gmail.com> wrote:
> No entiendo exactamente donde entra NH en la consullta.
> Es decir, el codigo que yo pienso para resolver eso al menos es
> independiente de la capa de persistencia, tambien los visitors  de Jose son
> independientes de la capa de persistencia.
>
> Creo que NH no es un factor para la decision de negocio. Podrias
> transformarlo en un factor si quisieras usar Listeners o alguna cosa
> especifica de NH para guardar el movimiento.
>
> En mi caso el servicio que guarda la factura y los detalles llama al
> Dao/Repositorio que sabe guardar una factura y sus detalles y se genera un
> evento de dominio para cada detalle de factura.
>
> Otro componente recibe esos eventos y se encarga de guardar los movimientos.
>
> Los visitors de Jose hacen algo parecido a eso, pero creo que tambien Jose
> para esos casos  favorece domain events hoy en dia :)
>
> Gustavo.
>

> 2010/2/15 Roberto Ramírez <jramirezle...@gmail.com>


>
>
>
> > Buenos días a todos.
>
> > ¿Puedo resolver con nhibernate esto o es un error en mi modelo?
>
> > Yo guardo una factura con su respectivo detalle, dentro de mi modelo
> > yo necesito generar un movimiento en inventario y por cada movimiento
> > guardar la referencia del detalle de la factura así:
>
> > Factura ==> Detalle ==> Movimiento
>
> > El proceso del movimiento al inventario es un paso intermedio al
> > momento de guardar-actualizar mi factura.
>
> > En mi modelo, el detalle de la factura no conoce los movimientos en el
> > inventario, pero el movimiento si conoce a que detalle de factura
> > pertenece.
>
> > ¿Como identificar la referencia del detalle para insertarla en el
> > movimiento si todo se ejecuta en un solo request (Session-Per-Request)
> > y aun no conozco la referencia del detalle que se guardo en la base de
> > datos?
>
> > Uso Visitor como patron de diseño tomado del post de J. Rommaniello

> >http://jfromaniello.blogspot.com/2009/11/caso-practico-patron-visitor...

Gustavo Ringel

unread,
Feb 15, 2010, 2:15:26 PM2/15/10
to nhibernat...@googlegroups.com
No, mas bien algo como esto:


Listeners de NH para algo que no es especifico de datos como la creacion de un movimiento quiere decir que a una regla de negocios la estas todavia atendiendo a nivel de datos.

A mi gusto Listeners de NH se pueden usar para auditoria, tracing, o cosas que son especificas de la capa de datos y que el dia que tiras la capa de datos no tienen mas utilidad para tu negocio.

Con Domain Events la idea es en el momento en que pasa algo avisar que paso por ejemplo DomainEvents.FacturaGuardada(new FacturaGuardadaEvent() { Factura = factura, Detalles = detallesList })

Vos tenes en algun lado un SalvarMovimientosHandler : Handles<FacturaGuardadaEvent> y al atender el evento guarda un movimiento en la base por cada detalle.


Gustavo.

2010/2/15 Roberto Ramírez <jramir...@gmail.com>
Muchas gracias por la respuesta Gustavo, me queda claro lo que

Roberto Ramírez

unread,
Feb 15, 2010, 2:21:51 PM2/15/10
to NHibernate-Hispano
Muchas gracias d00t

Entonces a lo que veo es que me toca buscar sobre Domain Events para
resolver mi problema, dejando fuera a NH de esto... y pues Visitor ya
lo había entendido, pero al parecer no me servirá..

Saludos... =)

On 15 feb, 11:15, Gustavo Ringel <gustavo.rin...@gmail.com> wrote:
> No, mas bien algo como esto:
>
> http://www.udidahan.com/2009/06/14/domain-events-salvation/
>
> <http://www.udidahan.com/2009/06/14/domain-events-salvation/>Listeners de NH
> para algo que no es especifico de datos como la creacion de un movimiento
> quiere decir que a una regla de negocios la estas todavia atendiendo a nivel
> de datos.
>
> A mi gusto Listeners de NH se pueden usar para auditoria, tracing, o cosas
> que son especificas de la capa de datos y que el dia que tiras la capa de
> datos no tienen mas utilidad para tu negocio.
>
> Con Domain Events la idea es en el momento en que pasa algo avisar que paso
> por ejemplo DomainEvents.FacturaGuardada(new FacturaGuardadaEvent() {
> Factura = factura, Detalles = detallesList })
>
> Vos tenes en algun lado un SalvarMovimientosHandler :
> Handles<FacturaGuardadaEvent> y al atender el evento guarda un movimiento en
> la base por cada detalle.
>
> Gustavo.
>

> 2010/2/15 Roberto Ramírez <jramirezle...@gmail.com>

Gustavo Ringel

unread,
Feb 15, 2010, 2:40:53 PM2/15/10
to nhibernat...@googlegroups.com
Si entendiste la idea de los visitors DomainEvents es una forma de hacer lo mismo pero en forma menos explicita, fijate en el comentario de Fabio al post de Jose, y acordate que por mas lindo que sea el martillo nuevo se usa un destornillador para un tornillo.

Gustavo.

2010/2/15 Roberto Ramírez <jramir...@gmail.com>
Muchas gracias d00t

José F. Romaniello

unread,
Feb 16, 2010, 6:59:36 AM2/16/10
to nhibernat...@googlegroups.com
Como dijo Gustavo, ahora voy mas por el camino de domainevents. La idea es parecida, pero me ahorro tener que especificar que tengo que inyectar.

Uso algo muy parecido a lo que esta en el blog de Udi Dahan, pero con ServiceLocator.

Ahora bien, cambiar de visitors a domain events creo que no te va a resolver el problema. Vos dijiste:

En mi modelo, el detalle de la factura no conoce los movimientos en el inventario, pero el movimiento si conoce a que detalle de factura pertenece. 
¿Como identificar la referencia del detalle para insertarla en el movimiento si todo se ejecuta en un solo request (Session-Per-Request) y aun no conozco la referencia del detalle que se guardo en la base de datos?


Y que importa que no se haya guardado en la base de datos todavía, nh no es tan burro. Pseudo código:

var factura = new Factura()
factura.AgregarLinea(new LineaFactura())
//domain event o lo que sea de por medio... pasando referencia a la factura
var movimiento = new Movimiento(){ Detalle = factura....Detalle[0] } 
session.Save(movimiento)

session.Save(factura)


En tu caso algo como esto debería funcionar, el truco tal vez esta en usar bien los cascades.. y ese tipo de cosas. Tal vez el save de movimiento debería desencadenar el save de línea, que a su vez desencadena el save de factura.

Creo que sobre este pseudocódigo podemos discutir, quiero decir saquemos de la discusión Visitors y DomainEvents. Lo dejo abierto.


si vos podes, escribí un test de comportamiento así, abris una sessión y ejecutas ese pseudocódigo que te pase. Y decinos que pasa, que sqls ves en el output etc.

Roberto Ramírez

unread,
Feb 16, 2010, 10:14:15 AM2/16/10
to nhibernat...@googlegroups.com
Gracias por tu ayuda José.

Comenzaré con cambiar un poco mi lógica y haré algo como lo que mencionas, analizaré el comportamiento y se los muestro...

Saludos cordiales.

--
Roberto Ramírez

2010/2/16 José F. Romaniello <jfroma...@gmail.com>

Roberto Ramírez

unread,
Feb 16, 2010, 3:12:41 PM2/16/10
to nhibernat...@googlegroups.com
Funcionó tal y como mencionas... el problema es que no asignaba la misma referencia de mi detalle en el movimiento, sino que en el movimiento asignaba una nueva instancia.

var factura = new Factura();
factura.AgregarDetalle(new Detalle());

foreach (var visitor in _visitors) {
   //Lógica que me indica si se moverá algo en el inventario.
   if (visitor.Aplica(factura)) {
      //Realizo el movimiento.
      visitor.Aplicar(factura);
   }
}

En el método Aplicar tenia:

public void Aplicar(Factura entidad) {
   MovimientoServices si = new MovimientoServices();
   IList<Detalle> detalles = List<Detalle>();
   foreach(Detalle linea in entidad.Detalle) {
      Detalle detalle = new Detalle() { Id = linea.Id }
      detalles.Add(detalle);
      var movimiento = new Movimiento(){ Detalle = detalles } 
   }
   si.Guardar(movimiento)
}

session.Save(factura)

Para corregirlo solamente agregue misma referencia a Detalle en mi Movimiento tal como comenta José:

public void Aplicar(Factura entidad) {
   MovimientoServices si = new MovimientoServices();
      var movimiento = new Movimiento(){ Detalle = entidad.Detalle } 
   }
   si.Guardar(movimiento)
}

El error fue mío...  nhibernate funciona correctamente; el tema de Visitor y DomainEvents esta fuera del alcance, y aunque DomainEvents me parece muy interesante, una vez corregida mi burrada, Visitor funciona de maravilla, aunque debo de admitir que un acercamiento a DomainEvents con este ejemplo explicado por alguno de ustedes me vendría de maravilla (off-topic por supuesto) =D

Dentro del output de SQL no veo nada raro, al menos que me ustedes me indiquen lo contrario. El orden de inserción fue de la siguiente manera:

1. Insert tabla de Factura.
2. Insert(s) tabla de Detalle (por cada línea o artículo).
3. Insert(s) tabla de Movimiento (por cada registro en Detalle).

Para mi lo interesante es conocer como nh le hace para insertar el idDetalle en la tabla de Movimiento

Saludos.

--
Roberto Ramírez


2010/2/16 José F. Romaniello <jfroma...@gmail.com>
Como dijo Gustavo, ahora voy mas por el camino de domainevents. La idea es parecida, pero me ahorro tener que especificar que tengo que inyectar.

José F. Romaniello

unread,
Feb 16, 2010, 3:32:51 PM2/16/10
to nhibernat...@googlegroups.com
Es por que nhibernate es una maaaaasa, cuando vos haces:
si.Guardar(movimiento)

no te esta insertando nada, solamente esta encolando eso para cuando se haga flush (end del request)

cuando vos haces: session.Save(factura) tampoco guarda nada nhibernate.


Recien cuando termina el request, en un batch, hace todos los inserts y en el orden que mas le conviene, no esta bueno?


Hay otras mil opciones, vos podrías tener una relación similar, solo que con un solo save . Entonces podes decir que te haga save en cascada de los objetos transitorios que no han sido persistidos todavía... en fin hay mil opciones.

Si tengo tiempo me voy a escribir el mismo ejemplo de visitors con domain events en castellano.

Roberto Ramírez

unread,
Feb 16, 2010, 4:47:13 PM2/16/10
to nhibernat...@googlegroups.com
En lo particular agradecería una lectura a ese ejemplo que mencionas... ayudaría bastante...

Y pues si, nh es genial, por eso lo uso, aunque sigo con dudas y creo que las seguiré teniendo, pero no importa es lo que entretiene y divierte =)
Reply all
Reply to author
Forward
0 new messages