On May 7, 2008, at 1:29 PM, Laurence Rowe wrote:

I'm thinking more about having the same classes mapped to different databases at different points in the application. Imagine a departmental address book app. Intstances of the departmental address book are created for each department, each with a different databases:

http://addressbook/sales -> postgres:///sales
http://addressbook/engineering -> postgres:///engineering

The way I imagine this working is to have a proxy engine object that looks up the real engine through a local utility. Each application would be a `site` and capable of local utility registrations. /sales would have Engine('postgres:///sales') registered and /engineering Engine('postgres:///engineering').

Only a single ScopedSession would be required. This would be bound to proxy that performs the utility lookup. So when in the /sales context the proxy would point to the sales engine and when in the / engineering context to the engineering engine.

The limitation of this approach is that it would not be possible to mix objects from /sales and objects from /engineering into the same transaction. So really we need a session per application instance. Perhaps this can be achieved through a custom scoping function:

def scopefunc():
   return thread.get_ident(), id(zope.component.getSiteManager())

If you want to mix tables (and optionally engines) for the *same* class, we actually have a feature for that too. Its sort of a feature I've wanted to remove but Jason keeps arguing that its worthy. It's called "entity_name" and it allows multiple primary mappers to be created for a single class. The entity_name has to be specified when you add the element to the session (yet another reason explicit add() is a good thing). This feature is taken directly from the Hibernate feature of the same name.

The limitation with entity_name which needs some more fixing in 0.5 is that only one mapper gets to define the attribute instrumentation for the entity. If you are storing the same class in three different tables (across three different databases or just one), the attributes defined on the class need to be compatible with all three. This is reasonable since a class can only have one descriptor per attribute name. Querying is also slightly challenging since the descriptors need to be qualified for a particular mapper (i.e. you cant just say query.filter(Address.id==5)...which "id" are we talking about ?)

The reason I'm not totally keen on this feature is that it seems to be a very exotic way of getting around making simple subclasses, and I've yet to see the use case for it where simple subclasses don't work, except for "cosmetic" reasons which I have a hard time swallowing (even if the reasons are "cosmetic", you can still create subclasses that are all "named" the same).

So I will ask you, why can't your application simply have a SalesAddress and an EngineeringAddress class ? You could even produce them transparently using a custom __new__() method, i.e.

class Address(object):
    def __new__(cls, *args, **kwargs):
        if my_scoped_thing.context == 'sales':
            return object.__new__(SalesAddress)
       elif my_scoped_thing.context == 'engineering':
            return object.__new__(EngineeringAddress)

this seems extremely straightforward to me as each object, once instantiated is now bound for a specific destination. It doesnt seem like youd want the *same* Address to be stored in one and then the other in a different instance (that seems *extremely* complex for no good reason). Isnt explicit better than implicit ?

Zope-Dev maillist  -  Zope-Dev@zope.org
**  No cross posts or HTML encoding!  **
(Related lists - http://mail.zope.org/mailman/listinfo/zope-announce
http://mail.zope.org/mailman/listinfo/zope )

Reply via email to