[altnet-argentina] Donde poner el Unit Of Work?

75 views
Skip to first unread message

Leandro Boffi

unread,
Apr 15, 2010, 8:33:18 PM4/15/10
to altnet-a...@googlegroups.com
Buenas, quisiera que debatamos lo siguiente...
 
Donde ponen el unit of work en una aplicacion no distribuida, utilizando DDD y ASP.NET MVC?
 
La duda me surge ya que en aplicaciones distribuidas, por lo menos a mi entender, el lugar ideal es la capa de servicios de aplicacion (siendo estos a la vez servicios web), pero en una aplicacion ASP.NET MVC no distribuida siento que podria remplazar esa capa de servicios de aplicacion por los controllers y poner ahi el unit of work.
 
Que opinan?

--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
Apr 15, 2010, 8:46:19 PM4/15/10
to altnet-a...@googlegroups.com
El patron que más se utiliza para ese tipo de aplicaciones es session per request.
Al igual que en Asp.Net, lo podes hacer por request, en un httpmodule.
Otros dicen que en asp.net mvc podes hacerlo en un actionfilter.

en fin busca session per request hay miles de ejemplos.

--
Desuscripción: altnet-argenti...@googlegroups.com

Leandro Boffi

unread,
Apr 15, 2010, 8:56:13 PM4/15/10
to altnet-a...@googlegroups.com
Bien, igualmente yo me referia a la decision arquitectonica de donde poner el codigo, mas que a la solucion tecnica.
 
Todos los pasos de una determinada transaccion, los escriben en el controller o hay una capa mas de servicios de aplicacion donde ponen todos esos pasos y al controller ya le llega resuelto?

2010/4/15 José F. Romaniello <jfroma...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
Apr 15, 2010, 9:07:38 PM4/15/10
to altnet-a...@googlegroups.com
Yo (y la mayoría), no ponemos "opensession" y "begintransaction" por todos lados, ni ninguna llamada a ningun lado que haga esas dos cosas. 

Patrón session per request

Teoría

Session y Transaction tienen el mismo ciclo de vida que el request web. Al iniciar un request se abre sessión e inicia la transacción al finalizar el request se commitea la transacción. Hay algunos casos donde no se abre session ni tx, por ejemplo cuando el request es por una imagen.

Técnica

Implementar de IHttpModule, similar a esto: http://is.gd/buKjx
Hacer lo mismo que lo anterior pero directamente en el application (global.asax) jfromaniello.blogspot.com/2009/11/como-usar-session-per-request-con.html
En asp.Net MVC hacerlo a nivel de attributo Gisela Buitragro tiene un excelente post en español al respecto... pero no puedo llegar a la dirección si alguien la agrega estaría barbaro.

Comentario

No me gusta ver opensession y begintransaction en ningun lado, ni si quiera una llamada a algo que haga esto.. Ya que este es el caso "B" de AOP (el caso A es logging). Transaction Management va como anillo al dedo con AOP..................
--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
Apr 15, 2010, 9:10:35 PM4/15/10
to altnet-a...@googlegroups.com
tal es el punto que no me gusta ver open session y begin transaction que estoy pensando hasta sacarlo de mis tests de integración de datos, este es un ejemplo:

Leandro Boffi

unread,
Apr 15, 2010, 9:33:55 PM4/15/10
to altnet-a...@googlegroups.com
ok, igual no me referia a eso, estoy de acuerdo en eso y de hecho yo lo hago utilizando actionfilters, pero mi pregunta iba a otra cosa...
 
A ver, para bajarlo a codigo, asi seria:
 
Opcion #1: Tengo un servicio de aplicacion que realiza todas las tareas para una determinada accion.
 
        public class ApplicationService
        {
            public int DoSomethingImportant(int id)
            {
                var repo = new DomainConceptRepository();
                
                 var entity = repo.Get(id);
                 entity.ChangeSomeStuffInTheModel();
                 entity.DoAnotherStuff();
 
                 return DomainService.Calculate(entity);
            }
        }
 
    public class ApplicationController : Controller
    {
        [PersistAction]
        public ActionResult SomeAction(int id)
        {
            var service = new ApplicationService();
            int result = service.DoSomethingImportant();
            return View(result);
        }
    }

 
Opcion #2: La lista de pasos para realizar una determinada tarea en el controller sin application Service
 
    public class ApplicationController : Controller
    {
        [PersistAction]
        public ActionResult SomeAction(int id)
        {
            var repo = new DomainConceptRepository();
            var entity = repo.Get(id);
            entity.ChangeSomeStuffInTheModel();
            entity.DoAnotherStuff();
            int result = DomainService.Calculate(entity);
            return View(result);
        }
    }
 
 
Actualmente lo tengo con la opcion #1, pero al estar hechos los metodos de los servicios de aplicacion para servir a una accion determinada no son muy reutilizables y siento que estoy agregando una capa mas sin mucho beneficio...
--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
Apr 15, 2010, 9:39:17 PM4/15/10
to altnet-a...@googlegroups.com
Yo hago las dos, dependiendo del caso.

1- inyecto irepository en el controller
2- inyecto irepository en un service, inyecto iservice en un controller.

En mi aplicación de ejemplo chinook media manager, que usa MVVM sobre WPF, inyecto irepository en model, inyecto un IModel en un ViewModel (que hace las veces de controller también).

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
Apr 15, 2010, 10:43:47 PM4/15/10
to altnet-a...@googlegroups.com
yo pondria todo en una capa diferente (en el repository, on en extension methods sobre el domain model?), y 

/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/4/15 Leandro Boffi <lbo...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Nelo Pauselli

unread,
Apr 15, 2010, 11:00:44 PM4/15/10
to altnet-a...@googlegroups.com
Opino que... primero deberíamos contestarnos la pregunta: ¿cual es la
UNIT of work en cada caso?... no creo que tengamos que decidir el
alcance de cada unidad de forma abstracta al problema a solucionar,
sino que debemos pensarlo en sentido inverso, del negocio a lo
técnico. Es como cuando se pregunta ¿donde pongo el manejo de una
transacción?... la respuesta está en el negocio, eso define a que
nivel va la transacción. Luego buscamos el patrón que mejor aplique
(session per request, session per call, session per conversation, etc
etc etc).

Entendiendo la UoW como un "espacio protegido" donde desde el interior
se ve el contenido y desde el exterior no, esto define cual es el
alcance de tu UoW.

que bueno que opinar es gratis... jeje.

Saludos
Nelo.



2010/4/15 Daniel Cazzulino <dan...@cazzulino.com>:
--
Desuscripción: altnet-argenti...@googlegroups.com

cibrax

unread,
May 13, 2010, 2:55:51 PM5/13/10
to AltNet-Argentina
En el caso de ASP.NET MVC, yo lo resolvi injectando los repositories y
el unit of work en el constructor del Controller. Y nunca extendi la
session (o transacciones) del unit of work mas alla de una operation
del controller, ya que no tiene sentido creo. Seria algo como esto,
(En mi caso, los repositories y el unit of work compartian un data
context de EF)

class MyControler : Controller
{
public MyController(IRepository repo1, IRepository repo2,
IUnitOfWork unitOfWork)
{
}

public ActionResult MyAction()
{
repo.DoSomething();
repo2.DoSomething();

unitOfWork.SaveChanges();
> >> 2010/4/15 José F. Romaniello <jfromanie...@gmail.com>
> >>>> 2010/4/15 José F. Romaniello <jfromanie...@gmail.com>
> Desuscripción: altnet-argenti...@googlegroups.com- Hide quoted text -
>
> - Show quoted text -

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 13, 2010, 3:30:03 PM5/13/10
to altnet-a...@googlegroups.com
no entendi para q necesitas dos repositories y la interface del unit of work afuera... :|


/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/13 cibrax <cib...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Leandro Boffi

unread,
May 13, 2010, 4:27:00 PM5/13/10
to altnet-a...@googlegroups.com
Yo lo manejo asi: El EF context lo creo por request, y todos los repositorios de mi aplicacion en realidad no son mas que "query containers" objetos que saben ejecutar tal o cual query sobre el object context...

Para esto tengo una EntityHttpApplication...

public abstract class EntityHttpApplication<TObjectContext> : HttpApplication
        where TObjectContext : IPersistableEntityContext
    {
        public TObjectContext ObjectContext { get; set; }

        private Func<TObjectContext> objectContextCreation;

        public EntityHttpApplication(Func<TObjectContext> objectContextCreation)
            : base()
        {
            this.objectContextCreation = objectContextCreation;

            this.BeginRequest += new EventHandler(this.OnBeginRequest);
            this.EndRequest += new EventHandler(this.OnEndRequest);
        }

        private void OnBeginRequest(object sender, EventArgs e)
        {
            this.ObjectContext = this.objectContextCreation.Invoke();
        }

        private void OnEndRequest(object sender, EventArgs e)
        {
            this.ObjectContext.Dispose();
        }
    }

y para usarlo desde los controllers tengo un EntityController...

public abstract class EntityController<TObjectContext> : Controller
        where TObjectContext : IPersistableEntityContext
    {
        /// <summary>
        /// Gets the Entity Framework object context
        /// </summary>
        protected TObjectContext ObjectContext
        {
            get
            {
                var entityApp = HttpContext.Current.ApplicationInstance as EntityHttpApplication<TObjectContext>;

                if (entityApp == null)
                {
                    throw new NotSupportedException("The current HttpApplication is not an EntityHttpApplication");
                }

                return entityApp.ObjectContext;
            }
        }
    }

El controller finalmente me queda asi...

   public class ProjectsController : EntityController<ProjectsObjectContext>
    {
        private ITenantsRepository repo;

        public ProjectsController()
        {
            this.repo = new TenantsRepository(this.ObjectContext);
        }

        internal ProjectsController(ITenantsRepository repository)
        {
            this.repo = repository;
        }

        public ActionResult Add([ModelBinder(typeof(Project))] Project project, string tenantName)
        {
            return TryAndPersist.It(() => 
            {
                var tenant = this.repo.GetWithProjects(tenantName);

                tenant.AddProject(project);

                return View(tenant.Projects);
            });
        }
    }


El TryAndPersist ejecuta el Func y llama a persitir el contexto dentro de un try catch...



2010/5/13 Daniel Cazzulino <dan...@cazzulino.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

cibrax

unread,
May 13, 2010, 5:04:59 PM5/13/10
to AltNet-Argentina
Tengo un modelo de EF con muchas clases, y particione eso en distintos
repositorios de acuerdo a los use cases (o modulos). No queria tener
un repositorio solo con miles de metodos como en uno de los proyectos
en que trabajamos :).
> > > >>>>>> Desuscripción: altnet-argenti...@googlegroups.com<altnet-argentina%2Bunsubscrib­e...@googlegroups.com>
>
> > > >>>>> --
> > > >>>>> Desuscripción: altnet-argenti...@googlegroups.com<altnet-argentina%2Bunsubscrib­e...@googlegroups.com>
>
> > > >>>> --
> > > >>>> Desuscripción: altnet-argenti...@googlegroups.com<altnet-argentina%2Bunsubscrib­e...@googlegroups.com>
>
> > > >>> --
> > > >>> Desuscripción: altnet-argenti...@googlegroups.com<altnet-argentina%2Bunsubscrib­e...@googlegroups.com>
>
> > > >> --
> > > >> Desuscripción: altnet-argenti...@googlegroups.com<altnet-argentina%2Bunsubscrib­e...@googlegroups.com>
>
> > > > --
> > > > Desuscripción: altnet-argenti...@googlegroups.com<altnet-argentina%2Bunsubscrib­e...@googlegroups.com>
>
> > > --
> > > Desuscripción: altnet-argentina+unsubscr...@googlegroups.com- Hide
> > quoted text -
>
> > > - Show quoted text -
>
> > --
> > Desuscripción: altnet-argenti...@googlegroups.com<altnet-argentina%2Bunsubscrib­e...@googlegroups.com>

Daniel Cazzulino

unread,
May 13, 2010, 6:05:27 PM5/13/10
to altnet-a...@googlegroups.com
es un buen punto ;)

ahora, lo interesante es discutir como particiona esto la gente. En otro proyecto en el q estoy tengo un IModelEntities q tiene el MUNDO, y despues tengo un IModelRepository q solo expone lo q tiene sentido. O sea q el "wrapper" y el q agrega commands sobre el "data context" es el repository, q por debajo tiene accesso al mundo.

Pero no se como harias para componer distintos "aspects" sobre el data context/entities/dal... voy a dejar un background thread pensando en esto porq lo voy a necesitar cuando el proyecto tengas mas de 2 meses de vida ;)
--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
May 14, 2010, 8:30:04 AM5/14/10
to altnet-a...@googlegroups.com
Yo no tengo mucha experiencia en EF, pero con nh hago actualmente esto; la interfaz de IDao<T>

    public interface IDaoReadOnly<T> 
    {
        T Get(object id);
        T GetProxy(object id);
        void Refresh(T entity);
        IEnumerable<T> Retrieve(Expression<Func<T, bool>> predicate);
        int Count(Expression<Func<T, bool>> predicate);
    }
   public interface IDao<T> : IDaoReadOnly<T>
    {
        T MakePersistent(T entity);
        void MakeTransient(T entity);
    }


(Esto lo copie de un post de Fabio, que no puedo encontrar)

Casi nunca tengo una dao especifica y siempre uso la generica.... En algunos casos tengo una especifica cuando no puedo hacer la consultar bien por linq... Pero si estamos hablando de EF no hay muchas más formas de escribir consultas..así que...
Aclaración el método Retrieve devuelve queryable también.

se puede hacer cosas así IDao<Customer> ...Retrieve(c => c.FirstName.StartWith("Dan"));

Pero cuando la consulta es compleja y/o muy utilizada en otras partes del sistema termino con algo así:

Retrieve(Customers.FirstNameStartingWith("Dan"));


donde prefered es un metodo estatico de la siguiente forma:

public static Expression<Func<Customer, bool>> FirstNameStartingWith(string value){
  return c => c.FirstName.StartWith(value);
}

Y por último, hay algo que hice para facilitarme escribir query objects con linq, y que me permite hacer cosas como estas:

Retrieve(Customers.FirstNameStartingWith("Dan") & !Customers.Prefered())

Es decir, puedo escribir query objects y aplicarle los operadores lógicos "&" "|" "!".


Con respecto al datacontext de nhibernate, que supongo representa la unit of work... para web empezaría utilizando session per request, ya sea registrandolo en los eventos BeginRequest y EndRequest de la aplicación... O con AOP sobre los actions del controller, puede ser con un ActionFilter.
--
Desuscripción: altnet-argenti...@googlegroups.com

Leandro Boffi

unread,
May 14, 2010, 8:53:39 AM5/14/10
to altnet-a...@googlegroups.com
Por lo general tengo un IModelObjectContext por modulo funcional de la aplicacion y luego distintos repositorios que no son mas que objetos que saben como ejecutar un query especifico sobre ese contexto.

Lo que no me gusta demasiado de tener un solo Dao o Repository generico que devuelva IQueryable es que las querys te quedan desperdigadas e incluso repetidas por toda la aplicacion, yo uso el repositorio como un encapsulador de queries y tengo un repositorio por "concepto de negocio" pero todos le pegan al mismo contexto, que suelen recibir como parametro en el constructor.

A lo sumo si en algun caso tengo una query dinamica, permito al repositorio recibir un func, pero solo en casos extraordinarios.


2010/5/14 José F. Romaniello <jfroma...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 9:01:55 AM5/14/10
to altnet-a...@googlegroups.com
'ta bueno lo de tener una clase estatica con query expressions q aplican a un "entity set". Customers.Preferred hasta podria ser una static property, creo.

Y para commands como haces?

Lo del IDao, a mi me gusta generarlo strong-typed con un T4 sobre el modelo de EF asi tengo intellisense. Tambien estoy jugando con un T4 q me genera interfaces para todas las entidades, asi tengo toda la API interface-based, y uso las mismas interfaces en el server (astoria) y en el cliente (astoria ;)). Pero todavia no puedo decir q este convencido 100%... quizas unos plain POCOs andarian, no sep.... siempre termino volviendo a la idea (de Fabio?) de no tener mas classes para DTOs y solo tener interfaces, y un solo uber-DTO al q le pones interfaces arriba... 

/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/14 José F. Romaniello <jfroma...@gmail.com>
Yo no tengo mucha experiencia en EF, pero con nh hago actualmente esto; la interfaz de IDao<T>

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 9:12:40 AM5/14/10
to altnet-a...@googlegroups.com
dao != repository

el dao son las entities y sus IQueryables.
el repository es el q agrega la logica de negocio. 
el punto es como haces para componer/"layerear" varios "aspects" de logica de negocio sobre el mismo dao/db y q sean facil de componer, asi no tenes q recibir dos repositories mas un unit of work como tenia Cibrax.

PD: q grande Cibrax reviviendo un thread de un mes de viejo :P


/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/14 Leandro Boffi <lbo...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

cibrax

unread,
May 14, 2010, 9:16:41 AM5/14/10
to AltNet-Argentina
Otro problema de tener un Repository<T>, es que eso va se lleva bien
de la mano con EF/DataServices en scenarios en que tenes que retornar
no solo T, sino que algunas relaciones de T. Como EF y Data Services
no soportan lazy loading, tenes que hacer que incluirl las relaciones
en la consulta inicial. Ahora si tenes, Cliente, y el Cliente tiene
ordenes. Si tenes un metodo Get<Cliente>(id), como sabes de antemano
que el codigo que esta consumiendo ese metodo va a necesitar el
cliente, y ademas todas las ordenes (por lo cual el repository deberia
hacer un include primero).

Pablo.


On May 14, 10:01 am, Daniel Cazzulino <dan...@cazzulino.com> wrote:
> 'ta bueno lo de tener una clase estatica con query expressions q aplican a
> un "entity set". Customers.Preferred hasta podria ser una static property,
> creo.
>
> Y para commands como haces?
>
> Lo del IDao, a mi me gusta generarlo strong-typed con un T4 sobre el modelo
> de EF asi tengo intellisense. Tambien estoy jugando con un T4 q me genera
> interfaces para todas las entidades, asi tengo toda la API interface-based,
> y uso las mismas interfaces en el server (astoria) y en el cliente (astoria
> ;)). Pero todavia no puedo decir q este convencido 100%... quizas unos plain
> POCOs andarian, no sep.... siempre termino volviendo a la idea (de Fabio?)
> de no tener mas classes para DTOs y solo tener interfaces, y un solo
> uber-DTO al q le pones interfaces arriba...
>
> /kzu
>
> --
> Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1
> 425.329.3471
>
> 2010/5/14 José F. Romaniello <jfromanie...@gmail.com>
>
>
>
> > Yo no tengo mucha experiencia en EF, pero con nh hago actualmente esto; la
> > interfaz de IDao<T>
>
> >     public interface IDaoReadOnly<T>
> >     {
> >         T Get(object id);
> >         T GetProxy(object id);
> >         void Refresh(T entity);
> >         IEnumerable<T> Retrieve(Expression<Func<T, bool>> predicate);
> >         int Count(Expression<Func<T, bool>> predicate);
> >     }
> >    public interface IDao<T> : IDaoReadOnly<T>
> >     {
> >         T MakePersistent(T entity);
> >         void MakeTransient(T entity);
> >     }
>
> > (Esto lo copie de un post de Fabio, que no puedo encontrar)
>
> > Casi nunca tengo una dao especifica y siempre uso la generica.... En
> > algunos casos tengo una especifica cuando no puedo hacer la consultar bien
> > por linq... Pero si estamos hablando de EF no hay muchas más formas de
> > escribir consultas..así que...
> > Aclaración el método Retrieve devuelve queryable también.
>
> > se puede hacer cosas así *IDao<Customer> ...Retrieve(c =>
> > c.FirstName.StartWith("Dan"));*
>
> > Pero cuando la consulta es compleja y/o muy utilizada en otras partes del
> > sistema termino con algo así:
>
> > *Retrieve(Customers.FirstNameStartingWith("Dan"));*
>
> > donde prefered es un metodo estatico de la siguiente forma:
>
> > public static Expression<Func<Customer, bool>> FirstNameStartingWith(string
> > value){
> >   return c => c.FirstName.StartWith(value);
> > }
>
> > Y por último, hay algo que hice para facilitarme escribir query objects con
> > linq, y que me permite hacer cosas como estas:
>
> > *Retrieve(Customers.FirstNameStartingWith("Dan") & !Customers.Prefered())*
>
> > Es decir, puedo escribir query objects y aplicarle los operadores lógicos
> > "&" "|" "!".
>
> >http://jfromaniello.blogspot.com/2009/12/linq-specifications-from-arg...
> ...
>
> read more »- Hide quoted text -

José F. Romaniello

unread,
May 14, 2010, 9:43:24 AM5/14/10
to altnet-a...@googlegroups.com


El 14 de mayo de 2010 09:53, Leandro Boffi <lbo...@gmail.com> escribió:
Lo que no me gusta demasiado de tener un solo Dao o Repository generico que devuelva IQueryable es que las querys te quedan desperdigadas e incluso repetidas por toda la aplicacion, yo uso el repositorio como un encapsulador de queries y tengo un repositorio por "concepto de negocio" pero todos le pegan al mismo contexto, que suelen recibir como parametro en el constructor.


Vos preferís tener un repositorio especifico con un metodo por query, mientras a mi me gusta tener las queries en clases separadas, preferentemente una clase por cada query. Incluso con linq podemos hasta darnos el lujo de decir, que la query no esta atada a la implementación del IRepository. Antes lo hacía como vos decís, pero en el repository me quedaba como una maraña de métodos con nombres impronunciables.

--
Desuscripción: altnet-argenti...@googlegroups.com

Leandro Boffi

unread,
May 14, 2010, 9:47:18 AM5/14/10
to altnet-a...@googlegroups.com
Yo veia a DAO como Data Access Object, un objeto de acceso a datos nomas, igualmente yo uso repositorios, pero los repositorios estan libres de logica de negocio, la logica de negocio la manejo en las entities, value objects o business services.

La otra es agregar entre el controller y el dominio, (con dominio me refiero a repositories, entities, value objects y business services) una capa de servicios de aplicacion, tipo el service layer de Fowler, algo que orqueste todo eso, maneje transacciones y demas temas tecnologicos y te de una api mas funcional para tu UI... 

De hecho la idea original de este thread era ver si usaban esa capa de servicios de aplicacion o si directamente usaban el dominio desde los controllers....

2010/5/14 Daniel Cazzulino <dan...@cazzulino.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
May 14, 2010, 9:47:58 AM5/14/10
to altnet-a...@googlegroups.com
El 14 de mayo de 2010 10:01, Daniel Cazzulino <dan...@cazzulino.com> escribió:
'ta bueno lo de tener una clase estatica con query expressions q aplican a un "entity set". Customers.Preferred hasta podria ser una static property, creo.

Y para commands como haces?

Yo dije IDao, no IRepository... y para mi mi IDao tiene 2 o 3 commands. Save, Update, Delete. (y el update es discutible)



 

Lo del IDao, a mi me gusta generarlo strong-typed con un T4 sobre el modelo de EF asi tengo intellisense.

Que tipo de intelliscence? Yo también tengo intelliscence en el Idao, no te entiendo.



 
Tambien estoy jugando con un T4 q me genera interfaces para todas las entidades, asi tengo toda la API interface-based, y uso las mismas interfaces en el server (astoria) y en el cliente (astoria ;)). Pero todavia no puedo decir q este convencido 100%... quizas unos plain POCOs andarian, no sep.... siempre termino volviendo a la idea (de Fabio?) de no tener mas classes para DTOs y solo tener interfaces, y un solo uber-DTO al q le pones interfaces arriba... 

Less than "Few" is GoF 

--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
May 14, 2010, 9:52:40 AM5/14/10
to altnet-a...@googlegroups.com
Bueno, como bien vos sabras la API de Linq, no tiene "nativamente" una forma de especificar un fetch join por ejemplo.

Por lo tanto otro metodo que tiene mi dao es este:
IEnumerable<T> Retrieve(Expression<Func<T, bool>> predicate, params Expression<Func<T,object>[] eagerProperties);

En el segundo parametro le decis que cosas no queres que vengan lazy.

Retrieve(c => c.Name.StartsWith("aa"), c => c.Country);

Cuando pegue la interfaz al primer mail borre este metodo, por que me pareció que iba a confundir, pero ya que sacamos el tema...
--
Desuscripción: altnet-argenti...@googlegroups.com

cibrax

unread,
May 14, 2010, 10:02:06 AM5/14/10
to AltNet-Argentina
Interesante lo que mencionas. Nunca se me habia ocurrido implementarlo
de esa forma. De todas formas, luego habria que amacarse para
transformar ese expression al modo pedorro de expresar eager loading
in EF/Data Services, que basicamente es un string con el nombre del
entity set, pero eso ya es otra historia.

Gracias por el tip
Pablo.

On May 14, 10:52 am, José F. Romaniello <jfromanie...@gmail.com>
wrote:

José F. Romaniello

unread,
May 14, 2010, 10:06:41 AM5/14/10
to altnet-a...@googlegroups.com
son 5 líneas, de código: http://pastie.org/960312
(robado de algún lugar)

--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
May 14, 2010, 10:07:40 AM5/14/10
to altnet-a...@googlegroups.com
perdón ese código te convierte un expression en memberinfo.... que para este caso es un propertyinfo, pero ahi le podes hacer Name o lo que sea...
--
Desuscripción: altnet-argenti...@googlegroups.com

Angel Java Lopez

unread,
May 14, 2010, 10:24:52 AM5/14/10
to altnet-a...@googlegroups.com
Hola gente!

Oia.... sobre:

> el repository es el q agrega la logica de negocio.

@kzu, habra un ejemplo? para dar mas contexto a esto.

Nos leemos!

Angel "Java" Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez


2010/5/14 Daniel Cazzulino <dan...@cazzulino.com>

dao != repository

el dao son las entities y sus IQueryables.
el repository es el q agrega la logica de negocio. 
el punto es como haces para componer/"layerear" varios "aspects" de logica de negocio sobre el mismo dao/db y q sean facil de componer, asi no tenes q recibir dos repositories mas un unit of work como tenia Cibrax.

PD: q grande Cibrax reviviendo un thread de un mes de viejo :P


/kzu

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 10:47:34 AM5/14/10
to altnet-a...@googlegroups.com
IModelRepository.Publish(vsixFile)

q internamente desarme el vsix, le saca el manifest info, crea 25 entities, elimina la existente si hay, etc. etc.


/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/14 Angel Java Lopez <ajlop...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 10:49:55 AM5/14/10
to altnet-a...@googlegroups.com
'ta cool. yo venia pensando algo similar abstraido para astoria/ef, pero devolviendo un IQueryable con mi propio query provider asi puedo trasformarlo pre-pasarlo a uno u otro en la forma en q lo esperan en su propio IQueryable. 

de esa forma en mis tests simplemente no haria nada la conversion...


/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/14 José F. Romaniello <jfroma...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Angel Java Lopez

unread,
May 14, 2010, 1:19:16 PM5/14/10
to altnet-a...@googlegroups.com
Hola gente!

Bien, gracias Daniel, ahora hay mas contexto... :-)

Veo que queres solucionar

x.Publish(vsixFile)

Por que no:
myVsixFileEntity.Publish()
?

Otra pregunta, porque poner el .Publish en IModelRepository? De que patron Repository estamos hablando? Debe ser algo distinto de:
http://martinfowler.com/eaaCatalog/repository.html

Que otros metodos tiene tu IModelRepository? Por que nacio bautizado Repository?

No me importa tanto como se llame, sino dar mas contexto a tu uso. Muchos que lean XRepository, me imagino, salta a lo de Fowler et alias. Si nos entendemos todos, lo podemos llamar IModelPatitoAmarillo... :-)... pero aun no me queda claro a que estas llamando ahi IModelRepository

Hmmm... imagine por un momento que estabas hablando de alguna cosa que los nuevos de Entity Framework 4 llaman Repository, es asi?

BTW:
http://www.codeproject.com/KB/database/ImplRepositoryPatternEF.aspx
http://stackoverflow.com/questions/520065/entity-framework-as-repository-and-unitofwork

Ah! revisando el thread completo, encuentro tu texto:


En otro proyecto en el q estoy tengo un IModelEntities q tiene el MUNDO, y despues tengo un IModelRepository q solo expone lo q tiene sentido. O sea q el "wrapper" y el q agrega commands sobre el "data context" es el repository, q por debajo tiene accesso al mundo.

Sigue igual en pie la pregunta: e pe que IModelRepository se llama Repository?
--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
May 14, 2010, 1:26:48 PM5/14/10
to altnet-a...@googlegroups.com
Si coincido con Ángel, puede que tenga sentido llamarlo Repository en tu contexto. Cuando leí "Repository"  yo pensé que hablábamos del patrón Repository (M.Fowler como bien cita Angel)

A lo que este patrón se refiere, creo que no tendría un método con ese nombre que hiciera tales cosas.

Sobre esto:

pero devolviendo un IQueryable con mi propio query provider asi puedo trasformarlo pre-pasarlo a uno u otro en la forma en q lo esperan en su propio IQueryable. 

Si mal no entiendo sería como un wrapper del IQueryableProvider, para poder soportar... otros providers?

Saludos,

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 1:41:02 PM5/14/10
to altnet-a...@googlegroups.com
Estamos hablando exactamente de lo mismo. Fowler dice en esa pagina:

"Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them,"

en ningun lado dice q tengan q ser queries o que. No me gusta mucho poner la logica en las entities mismas porq me gusta usar esas mas como DTOs (sobre todo en un escenario webservice/astoria).

Wrappear el IQueryable para hacer transparente el uso. O sea, el repository expone:

public IQueryable Users { get; }

en vez de devolver el queryable de EF, podria devolver uno mio q traduce lo q le pones despues a ese queryable via un extension method, algo tipo:

repository.Users.Include(x => x.Orders)

q traduzca ese include en lo q EF espera. 
quizas me fui al joraca y no pueda implementarlo nunca asi, pero lo copado de eso es que puedo tener ese "Include" en el codigo "posta" y sin embargo poder correrlo in-memory para los tests q van contra un in-memory array de Users.

/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/14 José F. Romaniello <jfroma...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Pedro Wood

unread,
May 14, 2010, 2:02:01 PM5/14/10
to altnet-a...@googlegroups.com
En mi libro dice otra cosa che ;-D

Mediates between the domain and data mapping layers using a
collection-like interface for accessing domain objects

Saludos,

Pedro Wood

2010/5/14 Daniel Cazzulino <dan...@cazzulino.com>:
--
Desuscripción: altnet-argenti...@googlegroups.com

Leandro Boffi

unread,
May 14, 2010, 2:03:09 PM5/14/10
to altnet-a...@googlegroups.com
Yo veo a esas "operations performed over them" como CRUD, pero no logica de negocios.

Yo los uso tipo DDD, para mi los repositorios son una forma que tienen las entidades de abstraerse del acceso a datos y la persistencia...

Por otro lado, poniendo logica de negocio que deberia ser de la entidad en otro lado te lleva a darle a ese "otro lado" mucho conocimiento sobre tu entidad y lo deja demasiado acoplado y rigido para mi gusto. Vease http://martinfowler.com/bliki/AnemicDomainModel.html.

A lo sumo si queres usar tus entities como DTOs y no queres que "viaje" el comportamiento por ahi una solucion seria agragarles comportamiento por medio de extension methods, pero te van a quedar cosas publicas que en realidad no tendrian porque serlo... ademas de que suena medio conejo...

Para testear los repositorios lo que hago es simplemente mockear mi IObjectContext creando un InMemoryObjectContext... con las interfaces nuevas de EF4 es muy facil...


2010/5/14 Daniel Cazzulino <dan...@cazzulino.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 2:10:35 PM5/14/10
to altnet-a...@googlegroups.com
poner las operaciones en la entidad no siempre te soluciona el problema. por ejemplo, q haces si una operacion en una entidad toca/agrega varias otras? ahi necesitas pasarle un repositorio entonces, y eso hace q no puedan ser extension methods porq serian estaticos, a menos q le pases el repositorio a cada operacion q lo necesite, yuck!!!

y si podes las operaciones en las entities, como evoluciona un sistema q usa (por ej.) User desde miles de modulos?? terminas con un User con miles de metodos??

yo me estoy inclinando por poner esa logica en el repositorio, quizas con repositorios especificos por area de aplicacion/modulo. Pero si, es logica bastante CRUD-like (mi escenario actual es astoria-based).

cuando tenga mas logica te cuento, pero para astoria/rest scenarios, modelas practicamente toda tu logica de aplicacion en terminos de REST standard verbs, asi q todo termina siendo bastante CRUD/query igual...

/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/14 Leandro Boffi <lbo...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Angel Java Lopez

unread,
May 14, 2010, 2:18:26 PM5/14/10
to altnet-a...@googlegroups.com
Hola gente!

Si, justamente la pagina de Fowler en linea, va a buscar mas info al libro de Patterns of EAA, y dice lo que menciona Pedro.

La frase marcada por @Kzu:


"Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them,"

yo siempre la interprete como "operaciones performed" sobre "set of objects". No operaciones cualesquiera sobre un objeto. De hecho, me puso a buscar algun ejemplo de Fowler o de los autores de ese capitulo del libro, pero no queda para nada ni siquiera un indicio, de la interpretacion de @kzu.

Lo de tener entities sin logica: siempre pienso que las entities deben tener la logica que LES CORRESPONDA. Si una entity queda con poca logica, porque asi es el dominio, me parece OK.

Hmmm... pero dejarlas sin logica, por un tema de tecnologia a usar... no se, me da cosita... :-)... Igual entiendo la postura de Daniel: le facilita todo el trabajo, a veces nos olvidamos de esas cosas, por ser mas papistas que el papa.

Con respecto a que hacer cuando una entidad toca a otras, en una operacion de logica de negocios.... Hmmm.... Sera una cuestion de ver si la logica se la encargamos a una Entidad, o sino, a algo que podriamos llamar Service, Workflow, EmpleadaAnita, o lo que sea. En general, en aplicaciones de empresa, termina siendo un reflejo de lo que hace algun empleado o sector. Ejemplo: nueva venta, implica por abajo: armar la factura, controlar credito del cliente, reservar stock, imputar contablemente, y quizas mandar orden de produccion si falta algo. No podria eso en la entidad Factura. Seria algo en Ventas.NuevaVenta(datosdelaventa...) o algo asi.


Nos leemos!

Angel "Java" Lopez


2010/5/14 Pedro Wood <pedro...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Leandro Boffi

unread,
May 14, 2010, 2:36:27 PM5/14/10
to altnet-a...@googlegroups.com
Si es una opreacion que toca, agrega varias entidades lo resuelvo en la entidad padre, que llama a un metodo de la hija, cada entidad hace lo que puede con los datos que conoce, la asignacion de este comportamiento en el 99% de los casos tendria que ser super natural...

Foo fooEntity = fooRepository.GetWithChilds(4);

fooEntity.AddChilds(aLotOfChilds);

context.SaveChanges();
....

// Y en la entidad Foo

public void AddChilds(IEnumerable<FooChilds> childs)
{
        foreach (var child in childs)
        {
                // Las reglas de negocio para saber si un child es valido estan en el child 
                child.ValidateAllComplexBusinessRules();
                this.Chids.Add(child);
        }
}

De ultima si hay alguna operacion de negocio que no podes meter en ninguna entidad pero que cambia algo en el dominio, para eso uso los business services...

Si tenes una entidad con miles de metodos quizas tiene demasiada responsabilidad, y hasta puede llegar a ser un god object, creo que la solucion para esta en el modelado, quizas hay que reverlo y modelar mejor...

De hecho es una buena señal, si tenes una entidad con demasiados metodos puede significar que tiene demasiadas responsabilidades... es algo que te lleva a pensar mejor el modelado, en cambio si lo metes en otro lado por ahi es menos visible...


2010/5/14 Daniel Cazzulino <dan...@cazzulino.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 2:47:43 PM5/14/10
to altnet-a...@googlegroups.com
O porq no:

new VentasRepository(entities).NuevaVenta(datosdelaventa) 

:P

ahora ese "repository" (si no te gusta el enfoque q le doy a ese termino) tiene su interface, otros componentes (i.e. viewmodels) pueden recibirlo como dependencia, y pueden ser testeados tb, etc.

Creo q el problema de fondo es q el data context de EF es efectivamente el unit of work Y el repository (en terminos estrictos, CRUD de entities y querying via linq), mientras esto q estoy haciendo yo y llamando "repository" seria lo q algunos estan llamando "service", workflow o guatever.

ahh! nombres!!

ship it!
--
Desuscripción: altnet-argenti...@googlegroups.com

Pedro Wood

unread,
May 14, 2010, 3:28:14 PM5/14/10
to altnet-a...@googlegroups.com
Si, Ship it ! Pero después hay que mantenerlo....

Y..... lo que pasa es que los nombres sirven para entendernos, para
una discusión en una lista ni hablar.
Pero salvo que desarrolles solo también sirven para que el otro
entienda que ahí usaste el repository pattern, si no vas a tener que
explicarle al resto del equipo como es tu idea de repository.

E incluso aunque programes solo, cuando volvés a algo que hiciste hace
un tiempo también te tenés que entender a vos mismo.

Me pasa que digo.....WTF ! quien m....programó esto ! ....ahh, fui yo.....WTF !
Pero que m.....quise hacer acá !.........ahhh.....si, ahora me
acuerdo.....WTF !!

;-P
--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
May 14, 2010, 4:54:46 PM5/14/10
to altnet-a...@googlegroups.com

q traduzca ese include en lo q EF espera. 
quizas me fui al joraca y no pueda implementarlo nunca asi, pero lo copado de eso es que puedo tener ese "Include" en el codigo "posta" y sin embargo poder correrlo in-memory para los tests q van contra un in-memory array de Users.


Bueno, esto es casi lo mismo que yo hago. Te cuento con mi IDao no uso mocks para queries (pero si uso mock para la parte command), mas bien lo que uso para DAO es un stub, que internamente tiene una lista en memoria. Cuando pruebo estas cosas no estoy probando la query en ningún sentido mas que el básico, por ejemplo;

yo suelo inyectar un idaofactory; de esta forma lo creo

var daoFactory = new DaoFactoryStub().AddDao(new DaoStub<User>().AddEntity(new User("kzu","supass"));
var authService = new ValidationService(daoFactory);
var result = authService.Validate("kzu","dasdsa")
result.Messages.First().Satisfy(m => m.Type = ValidationResults.WRONG_PASSWORD);

Ahora... si internamente el servicio de autenticación, usa Retrieve.. o Retrieve con eager sobre alguna propiedad, al test no le importa... Eso lo pruebo de otra forma. Como tampoco voy a verificar que haga la consulta de la forma más optima, por decir;

Retrieve(u => u.UserName = ...).Count() == 1 o
Retrieve(u => u.UserName == ).Any() o
Retrieve(u => u.UserName == ).FirstOrDefault() == null.

Son cosas, que llegado el caso busco la vuelta de probarlas de otra forma, por ejemplo inyectando el verdadero dao, con una session corta y validando la cantidad de queries que se ejecutaron... por decir.

--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 7:45:34 PM5/14/10
to altnet-a...@googlegroups.com
suena bien. no veo bien ahi como usas lo del retrieve, pero asumo q el dao stub no hace nada con esa llamada.

bueno, me convencieron de renombrar mi "entities" a "repository" y el "repository" a "service" o algo por el estilo ;). 

el problema es q especialmente en un entorno como visual studio, un "service" tiene una connotacion especial, supongo al igual q en un entorno de webservices... 


/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/14 José F. Romaniello <jfroma...@gmail.com>

--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
May 14, 2010, 8:28:40 PM5/14/10
to altnet-a...@googlegroups.com
suena bien. no veo bien ahi como usas lo del retrieve, pero asumo q el dao stub no hace nada con esa llamada.

DaoStub tiene un metodo retrieve de esta forma

public IEnumerable<T> Retrieve<T>(Expression<Func<T,bool>> predicate){
 return entityList.Where(predicate);
}

La implementación del metodo "validate" sería algo así

public ValidationResult Validate(string userName, string password){
   var user = daoUser.Retrieve(u => u.UserName = userName).FirstOrDefault();
   if(user == null) return ValidationResult.InvalidUserName;
   if(user.Password != password) return ValidationResult.InvalidPassword;
   return ValidationResult.OK;
}

estoy inventando código al vuelo, lo que quería decir es que para ESTE test no calienta si llamo a 
var user = daoUser.Retrieve(u => u.UserName = userName).FirstOrDefault();
o a 
var user = daoUser.Retrieve(u => u.UserName = userName, u => u.Country).FirstOrDefault(); //

expandiendo por country, esta query ejecutaría algo como

select .. from user inner join country on c.... = user.countryid .. que se yo

Ni tampoco pongo muchas condiciones sobre como el service tiene que hacer el query..



--
Desuscripción: altnet-argenti...@googlegroups.com

Daniel Cazzulino

unread,
May 14, 2010, 10:23:04 PM5/14/10
to altnet-a...@googlegroups.com
me parece q no me exprese bien. yo habia entendido q tu Retrieve lo q hacia era especificar las relaciones para traer con lazy loading, no el simple predicate a aplicar en un Where...


/kzu

--
Daniel Cazzulino | Developer Lead | XML MVP | Clarius Consulting | +1 425.329.3471


2010/5/14 José F. Romaniello <jfroma...@gmail.com>
suena bien. no veo bien ahi como usas lo del retrieve, pero asumo q el dao stub no hace nada con esa llamada.


--
Desuscripción: altnet-argenti...@googlegroups.com

José F. Romaniello

unread,
May 15, 2010, 10:13:14 AM5/15/10
to altnet-a...@googlegroups.com
el primer parametro es el predicado, el segundo parametro las propiedades que queres "expandir". Es decir, una propiedad que esta mapeada como lazy load, para esta consulta, la quiero no-lazy.
--
Desuscripción: altnet-argenti...@googlegroups.com

Gustavo Azcona

unread,
May 15, 2010, 8:21:10 PM5/15/10
to altnet-a...@googlegroups.com

Hola a todos!

 

Me engancho un poco tarde en este thread solo para comentar que me gusta pensar a las entidades como simples DTOs inanimados (sin comportamiento) y disponer de clases (business) que le dan vida a esas entidades.

 

En el desarrollo de aplicaciones de negocio, nunca me termina de convencer la idea de que una entidad sabe como validarse y guardarse sola. Pues nunca vi a una factura real auto-completarse, pagarse, contabilizarse y guardarse sola. Siempre hubo alguien que lo hizo, generalmente un empleado/a del área de facturación.

 

Quizás haya escenarios reales que valen la pena, pero no me he encontrado con esa necesidad.

 

Disculpen, creo que ya me fui del tema principal.

Saludos

~Gus

 

cid:image003.jpg@01C8A203.9AF70260

gustavo azcona | .net architect | gustavo...@avanic.com.ar | (+54 911) 6229-6045 | gustavoazcona.blogspot.com

No virus found in this incoming message.
Checked by AVG - www.avg.com
Version: 9.0.819 / Virus Database: 271.1.1/2876 - Release Date: 05/15/10 15:26:00

--
Desuscripción: altnet-argenti...@googlegroups.com
image001.jpg

daniel...@gmail.com

unread,
May 15, 2010, 8:31:14 PM5/15/10
to altnet-a...@googlegroups.com
Yo tampoco creo que la entidad xxx deba saber guardarse.
Lo que debe saber hacer es atender sus responsabilidades directas.
La base del paradigma OO es la simulacion, crear artefactos que de alguna forma simulen los componentes del problema a resolver.
En ese contexto es logico que, poejemplo, un asiento contabla tenga como responsabilidad indicar si balancea o no, una cuenta contable informar su saldo, etc.

Solo una opinion sobre el tema...

Saludos

Daniel Calvin

Enviado desde mi BlackBerry de Movistar (http://www.movistar.com.ar)


From: "Gustavo Azcona" <gustavo...@avanic.com.ar>
Date: Sat, 15 May 2010 21:21:10 -0300
Subject: RE: [altnet-argentina] Re: Donde poner el Unit Of Work?

--
Desuscripción: altnet-argenti...@googlegroups.com

--
Desuscripción: altnet-argenti...@googlegroups.com
image001.jpg

José F. Romaniello

unread,
May 15, 2010, 9:07:28 PM5/15/10
to altnet-a...@googlegroups.com
Bah! yo opino igual que Daniel Calvin y Angel... En mi humilde opinión;

  • Como dijo Angel Lopez, no ponerle comportamiento a las entidades de negocio, solo por una cuestión técnica, como querer enviarlas por el cable me parece mal.
  • Muchas veces he visto cosas como ClienteDTO y para mi esta un poco mal. Es como que el DTO al igual que un ViewModel, que es un tipo especifico de DTO, estan MUY atados al USO y es muy dificil generalizar un DTO. Por lo cual me parece mas coherente encontrar en una aplicación MVC algo como EditarClienteViewModel cobra mucho sentido.
  • También veo un poco de ruido o mala interpretación, en las discusiones que hay alrededor de ORM. Como por ejemplo el tema de que "EF soporte POCO" no significa que voy a escribir en mi dominio solamente clases con autoproperty... Mas bien significa que el orm puede mapear hasta este tipo de clases, sin interferir o invadir tu código, con cosas que el framework necesite. Esto quiere decir que uno tiene 100% de control sobre la clase, y esta perfecto que metas  comportamiento especifico del dominio que esa clase esta representando.



El 15 de mayo de 2010 21:21, Gustavo Azcona <gustavo...@avanic.com.ar> escribió:

Hola a todos!

 

Me engancho un poco tarde en este thread solo para comentar que me gusta pensar a las entidades como simples DTOs inanimados (sin comportamiento) y disponer de clases (business) que le dan vida a esas entidades.

 

En el desarrollo de aplicaciones de negocio, nunca me termina de convencer la idea de que una entidad sabe como validarse y guardarse sola. Pues nunca vi a una factura real auto-completarse, pagarse, contabilizarse y guardarse sola. Siempre hubo alguien que lo hizo, generalmente un empleado/a del área de facturación.

 

Quizás haya escenarios reales que valen la pena, pero no me he encontrado con esa necesidad.

 

Disculpen, creo que ya me fui del tema principal.

Saludos

~Gus

 

cid:image003.jpg@01C8A203.9AF70260

gustavo azcona | .net architect | gustavo...@avanic.com.ar | (+54 911) 6229-6045 | gustavoazcona.blogspot.com

 

De: altnet-a...@googlegroups.com [mailto:altnet-a...@googlegroups.com] En nombre de José F. Romaniello
Enviado el: sábado, 15 de mayo de 2010 11:13 a.m.
Para: altnet-a...@googlegroups.com
Asunto: Re: [altnet-argentina] Re: Donde poner el Unit Of Work?

 

el primer parametro es el predicado, el segundo parametro las propiedades que queres "expandir". Es decir, una propiedad que esta mapeada como lazy load, para esta consulta, la quiero no-lazy.

No virus found in this incoming message.


Checked by AVG - www.avg.com
Version: 9.0.819 / Virus Database: 271.1.1/2876 - Release Date: 05/15/10 15:26:00

--
Desuscripción: altnet-argenti...@googlegroups.com
image001.jpg

José F. Romaniello

unread,
May 15, 2010, 9:08:47 PM5/15/10
to altnet-a...@googlegroups.com
BTW esta buenisimo el thread por que son como 10 temas entrelazados... no entiendo una goma de que estamos hablando

--
Desuscripción: altnet-argenti...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages