ibatis-user-cs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Carlos Peix" <peix-lis...@praxia.com.ar>
Subject RE: Kind of architecture question
Date Tue, 08 May 2007 17:06:57 GMT
Hi Bob,

You got it right, Customers and Orders are aggregate roots, that's why I define
two repositories. Anyway, that's a fake domain model, I just used familiar
concepts to back my post.

I see your approach, thanks. That's a solution, I'm concerned, tough, on
repeating my self on the definitions of relations. If the relation between
Application and ApplicationUser changes I should check (besides the domain
itself) the mapping code and the repositories code.

Anyway, thanks for taking the time to answer, I appreciate it.

Carlos 

> -----Original Message-----
> From: Bob Hanson [mailto:mnbob70@gmail.com] 
> Sent: Martes, 08 de Mayo de 2007 01:05 p.m.
> To: user-cs@ibatis.apache.org; peix-listas@praxia.com.ar
> Subject: Re: Kind of architecture question
> 
> I think it really boils down to how you choose to implement 
> your domain. In your example below, why does Order reference 
> customer? Is Order an aggregate? If not, all access to Order 
> should be through Customer and then you don't need a reference.
> 
> foreach ( Order order in customer.Orders ) {
>     Console.WriteLine( "Order #{0} from {1}", order.Number, 
> customer.Name ); }
> 
> Otherwise, here are some things I have done: (.NET 2.0) My 
> domain classes implement IEquatable<T> which does a deep 
> comparison. I might not have an equal reference so I check 
> for data equality instead. The simplest implementation could 
> just compare Ids but that presents a problem when checking 
> for "dirty" data.
> 
> Reference example: I have an Application class which contains 
> a list of ApplicationUsers (sub-class of User). An 
> ApplicationUser is a User of an Application (has a reference 
> to the Application) with a list of Roles for that 
> Application. My domain defines an interface 
> IApplicationRepository. I have a single repository implementation
> (IBatisRepository.Repository) which implements all of my 
> repository interfaces. The repository method that returns an 
> application (with all of its application users via a sql 
> join) assigns a reference AFTER the query completes:
>         public Application GetApplication(string applicationName)
>         {
>             Application application =
> SqlMapper.Instance().QueryForObject<Application>("SelectApplic
> ationByName",
> applicationName);
>             if (application != null)
>             {
>                 foreach (ApplicationUser user in application.Users)
>                 {
>                     user.Application = application;
>                 }
>             }
>             return application;
>         }
> 
> 
> On 5/8/07, Carlos Peix <peix-listas@praxia.com.ar> wrote:
> >
> >
> > Hi Tom,
> >
> > Yes, I know that it's not IBatis concern, I'm not asking 
> Gilles to add 
> > support for this.
> >
> > But this operation mode (to stop calling this an issue :-) not only 
> > gives me different instances of the same object (I can fall in the 
> > trap modifying one object and reading another unmodified 
> instance in 
> > may code) but it have performance implications.
> >
> > Think for a minute in the example I posted (it's below you 
> answer in 
> > this post). Imagine that the customer holds a reference to the 
> > collection of orders, something like:
> >
> > Customer {
> >     // Mapped collection, with getter and setter, of course.
> >     private IList orders;
> > }
> >
> > and the order has a reference to the Customer, just like 
> the example below.
> >
> > if I code this way:
> >
> > Customer customer = CustomerRepository.GetById( 1 );
> >
> > and then I do (in another method, down the code path):
> >
> > foreach ( Order order in customer.Orders ) {
> >     Console.WriteLine( "Order #{0} from {1}", order.Number, 
> > order.Customer.Name ); }
> >
> > I'm loading the customer again with all the orders (I know 
> I can use 
> > lazy load for this or that I can send the original customer 
> instance).
> >
> > I just want to know how other people is handling this.
> >
> > Thanks
> >
> > Carlos
> >
> >
> >  ________________________________
> >  From: Nguyen, Tom [mailto:Tom.Nguyen@rels.info]
> > Sent: Martes, 08 de Mayo de 2007 11:28 a.m.
> > To: user-cs@ibatis.apache.org
> > Subject: RE: Kind of architecture question
> >
> >
> >
> >
> >
> > I agreed with Sam that this should not be a concern for 
> iBatis.  I've 
> > also battled with the same issues in the pass, but I've found that 
> > it's much easier to use SQL for controlling of identity and 
> > concurrency (through various methods such as comparison of 
> OriginalValue or LastModifiedDate).
> >
> >
> >
> >
> >
> > Repository implementation is a can of worm in itself.  I 
> prefer to use 
> > light weight object and don't have to worry about issues such as 
> > multi-threading, caching and releasing references for Garbage 
> > Collector when it's not being reference.  Also, you can't really 
> > ensure identical object references in a webfarm or multiple 
> application server SOA implementation.
> >
> >
> >
> > On the other hand, I had a very specific need of repository base on 
> > lookup business objects such as OrderType, BusinessType, 
> ContactType, 
> > etc…  In this case, I implement custom in-memory caching 
> (repository).  
> > It's a very specific implementation which allow me to lazy load 
> > objects by identity
> > (key) and type, cache, timely clearing of cache for GC, etc..
> >
> >
> >
> >
> > Regards,
> >
> >
> > Tom Nguyen
> > Sr. Developer
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > On 5/7/07, Carlos Peix <peix-listas@praxia.com.ar> wrote:
> >
> >
> > Hi Shane, thanks for taking the time to answer.
> >
> >
> >
> > Yes, you are talking about an Identity Map I guess, but 
> this solution 
> > is harder to implement and tune. It's my last resort though.
> >
> >
> >
> > Of course, definitely the select="CustomerById" needs to be 
> removed. 
> > In fact, the command CustomerById uses a different cache that the 
> > command CustomerAll so, if we use cache for both commands 
> we can stop 
> > IBatis building different instances.
> >
> >
> >
> > One approach I used is for resolving this is implementing the
> > CustomerRepository.GetAll() with an IBatis query (cached) and the
> > CustomerRepository.GetById() resolved in memory. But I'm not very 
> > happy with this solution either
> >
> >
> >
> > Of course, the Order ResultMap just get the Customer Id and 
> I resolve 
> > the property getter or setter that way.
> >
> >
> >
> > class Order {
> >
> >
> >
> >     // This field is mapped in IBatis
> >
> >     object customerId;
> >
> >
> >
> >     // this is a transient field
> >
> >     private Customer customer;
> >
> >
> >
> >     public Customer Customer
> >
> >     {
> >
> >         get {
> >
> >             if ( customer == null )
> >
> >                 customer = CustomerRepository.GetById( customerId );
> >
> >             return customer;
> >
> >         }
> >
> >         set { customerId = value.Id; }
> >
> >     }
> >
> >
> >
> > }
> >
> >
> >
> > Carlos
> >
> >
> >
> >  ________________________________
> >
> >
> > From: Shane Courtrille [mailto:shanecourtrille@gmail.com]
> > Sent: Lunes, 07 de Mayo de 2007 07:03 p.m.
> > To: user-cs@ibatis.apache.org; peix-listas@praxia.com.ar
> > Subject: Re: Kind of architecture question
> >
> >
> > I'm just learning iBatis.Net now but I have used the repository <-> 
> > mapper pattern in the past.  Usually what I have done is have the 
> > repository contain a reference to a cache.  It checks the 
> cache before 
> > using the mapping layer to retrieve the item.  The problem I see is 
> > your Order select="CustomerById".  Without knowing more 
> about iBatis I 
> > would suggest you may need to remove that and instead have your 
> > repository fill in the reference after it gets the Order.  
> Definitely 
> > not a solution I'm in love with though.
> >
> > Shane
> >
> >
> > On 5/7/07, Carlos Peix <peix-listas@praxia.com.ar> wrote:
> >
> >
> > Hi all,
> >
> >
> >
> > I used IBatis.NET with success in various projects now but 
> I am still 
> > not very happy with my implementations. I'll try to explain 
> my concerns.
> >
> >
> >
> > My environment is .NET 1.1 but I think .NET 2.0 is the same 
> thing. I 
> > should say that I try to work guided by the DDD principles, so I 
> > access the final store through repositories.
> >
> >
> >
> > I have, for example, an entity Customer (aggregate root or simply a 
> > persistent identifiable object) and a CustomerRepository with the 
> > following
> > interface:
> >
> >
> >
> > Customer CustomerRepository.GetById( object id );
> >
> > IList CustomerRepository.GetAll();
> >
> > ...
> >
> >
> >
> > and I also have a Order and OrderRepository with the following 
> > interface
> >
> >
> >
> > OrderRepository.GetByNumber( int number );
> >
> > ...
> >
> >
> >
> > The problem I face all the time with IBatis is the I get different 
> > instances if I do:
> >
> >
> >
> > // implemented with a Mapper.QueryForObject( "CustomerById", id );
> >
> > Customer customer1 = CustomerRepository.GetById( object id );
> >
> >
> >
> > // implemented with a Mapper.QueryForList( "CustomerAll" );
> >
> > Customer customer2 = CustomerRepository.GetAll()[0];
> >
> >
> >
> > // implemented with a Mapper.QueryForObject( 
> "OrderByNumber", number 
> > );
> >
> > // and Customer mapped this way in the OrderResultMap:
> >
> > //  <result property="customer" column="CustomerId" 
> > select="CustomerById" /> Customer customer3 = 
> > OrderRepository.GetByNumber( 100 ).Customer;
> >
> >
> >
> > But customer1.Id, customer2.Id and customer3.Id are the same.
> >
> >
> >
> > Ok, this is a situation that need to be controlled, 
> otherwise I could 
> > modify or check different instances of the same object. I was told 
> > previously that this is not an IBatis problem and I see why 
> (in fact 
> > IBatis doesn't know anything about object identity, so it 
> can't control this).
> >
> >
> >
> > The question is: how are you structuring your code to control that 
> > situation? there are some "recommended practices"? I 
> started with some 
> > ideas (one of them include IBatis cache configuration) but I'm not 
> > happy with any of them.
> >
> >
> >
> > Sorry about the long post and thanks in advance.
> >
> >
> >
> > Carlos Peix
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >  ________________________________
> >
> >
> >
> > Princeton Retirement Group, Inc - Important Terms
> >
> > This E-mail is not intended for distribution to, or use by, 
> any person 
> > or entity in any location where such distribution or use would be 
> > contrary to law or regulation, or which would subject 
> Princeton Retirement Group, Inc.
> > or any affiliate to any registration requirement within 
> such location.
> >
> > This E-mail may contain privileged or confidential 
> information or may 
> > otherwise be protected by work product immunity or other 
> legal rules. 
> > No confidentiality or privilege is waived or lost by any 
> mistransmission.
> > Access, copying or re-use of information by non-intended or 
> > non-authorized recipients is prohibited. If you are not an intended 
> > recipient of this E-mail, please notify the sender, delete 
> it and do 
> > not read, act upon, print, disclose, copy, retain or 
> redistribute any portion of this E-mail.
> >
> > The transmission and content of this E-mail cannot be 
> guaranteed to be 
> > secure or error-free. Therefore, we cannot represent that the 
> > information in this E-mail is complete, accurate, 
> uncorrupted, timely 
> > or free of viruses, and Princeton Retirement Group, Inc. 
> cannot accept 
> > any liability for E-mails that have been altered in the course of 
> > delivery. Princeton Retirement Group, Inc. reserves the right to 
> > monitor, review and retain all electronic communications, including 
> > E-mail, traveling through its networks and systems (subject 
> to and in 
> > accordance with local laws). If any of your details are 
> incorrect or 
> > if you no longer wish to receive mailings such as this by 
> E-mail please contact the sender by reply E-mail.
> >
> >  ________________________________
> >
> >
> >
> >  ________________________________
> >
> >
> >
> >
> > This e-mail message and any files transmitted herewith, are 
> intended 
> > solely for the use of the individual(s) addressed and may contain 
> > confidential, proprietary or privileged information.  If 
> you are not 
> > the addressee indicated in this message (or responsible for 
> delivery 
> > of this message to such person) you may not review, use, 
> disclose or 
> > distribute this message or any files transmitted herewith.  If you 
> > receive this message in error, please contact the sender by reply 
> > e-mail and delete this message and all copies of it from 
> your system.
> >
> >  ________________________________
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> 


Mime
View raw message