Re: [sqlalchemy] Another Parent instance is not bound to a Session; lazy load...

2012-05-31 Thread Maurizio Nagni
First of all thanks to all of you for your answers and time. Michael let me 
say that I agree 100% with all you wrote and my will/wish is to work as you 
wrote, but when you are inside the ORM its easy, other is if you want to 
interact with the ORM from outside.

In my actual system I have more than 500 tables automatically generated 
from a UML model. Not all of them have a central role but all of them do 
something in the data model. If I want to fill one of the highest level 
object its attributes are classes their self with other attributes which 
are classes again; because I cannot simply send a few primitive parameters 
to the a function-ORM-aware and make the function create that object I am 
forced to create locally (in the GUI application) such object and their 
children (some of them can be NOT NULL so I cannot avoid it) then send the 
full object to the ORM interface.

Apart the great advantages that an ORM offers it should be possible to 
install it as a service, that is separate it from the any other 
application: in other words I can have a library of objects (like I have) 
shared among several GUI/WEB applications and an ORM. The communication 
between the applications and the ORM should be done serializing and 
deserializing instances of objects in the shared library. As example you 
can take the remote interface for an EJB in Java (btw I am thinking about 
the stateless interface). In this way the ORM does have not to expose to 
other applicaitons it's session (or EntityManager in EJB) but just an 
interface. Still in other words the rules that I impose on how I manage my 
database (that is one or more method using session/transaction), should be 
independent from the way I display/control them. Again: I would like to use 
SA as the MODEL of a Model-View-Controller strategy and because of this I 
can have a myriad of views/controlles but just one separate model 
application acting as service.

Now I am aware that my application is not decoupled as I want (Django 
initialize the SQL engine) so I cannot avoid SA to inject instruments in 
new instances but nonetheless I would expect that I may be able to work 
with objects in two separate universes: the GUI and the ORM.

When I wrote that I feel to have missed something I was referring to this: 
it seems to me that I cannot use SA in a remote-like way, creating an 
object in the GUI and then send it to the ORM, being sure that because the 
ORM maps such object it knows how to persist it or eventually retrieve it 
because it know where to catch the key for each mapped object.

For all the rest, thanks for your great software.
Maurizio

P.S.
If you are curious about the system I am working on just take a brief look 
at it here http://cedadocs.badc.rl.ac.uk/905/ or 
herehttp://jenkins.badc.rl.ac.uk/cedaManager/cov/1

On Thursday, May 31, 2012 4:50:38 AM UTC+1, Michael Bayer wrote:


 On May 30, 2012, at 8:53 PM, Claudio Freire wrote: 

  
  Thing is, in order to work with a large volume of objects, you're 
  forced to do this, otherwise the session can grow uncontrollably. 

 flush periodically, and don't maintain references to things you're done 
 with.  The Session does not strongly reference objects that have no pending 
 changes, and they'll be garbage collected. 


  When 
  you separate the operation to work in batches, you almost always have 
  some objects that have a lifespan larger than a single batch, and then 
  a single session. 

 Working in batches is fine.  You only need a single Session for all those 
 batches, and a single transaction.If you want several transactions, 
 also fine, call commit() periodically.  In none of these cases does the 
 Session need to be closed, and all objects worked with thus far which are 
 still referenced in memory can remain attached to that Session, and you 
 wont have any detachment errors. 

 The problems you're having are from unnecessary detachment of objects, 
 from calling Session.close() and continuing to work with objects that have 
 lost their owning Session, within the context of a new Session they have no 
 association with.   

  
  Another case in which an object's lifespan can exceed the session's, 
  is when you want to implement caching with objects of your data model 
  - cached values will have come from other sessions than the current 
  one, and things get horribly messy. 

 There are documented patterns for caching - see the example in 
 examples/beaker_caching in the distro.   This pattern is designed to 
 cleanly handle the pattern of detached objects becoming re-associated with 
 a particular session at once.   The pattern is along the lines of, session 
 is created to work with a field of objects, a set of objects is retrieved 
 from the cache, then re-associated with the cache en-masse using the 
 merge_result() method illustrated in the example. 





-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this 

[sqlalchemy] Another Parent instance is not bound to a Session; lazy load...

2012-05-30 Thread Maurizio Nagni
Hello all,

my curious situation is the following. A very simplified version of the 
code is:

for data in res:
 obj = MyObject()
 ---here I fill the obj, aventually doing some query (create session, 
get, close) to SA

 sess = createSession()
 sess.add(obj)
 sess.commit()
 sess.close()

 -- do some other query (create session, get, close) and eventually 
persist the changes (create session, merge/add, commit close)

now... on the first loop it works fine, then I receive the Parent 
instance warning me that a an obj inner attribute, say a contact, is 
not bound so cannot load contact.phone attribute. BTW I receive such 
message  when I commit() but I am able to make it appear looking in the 
second loop, during a debugging session, at the specific obj attribute.

What I would like to implement is to restrict the session (in a more 
general sense SA activity even if I know that actually SA inject some 
instrumentation in obj at the creation time) inside a unique class, say 
with some static methods (the code above involving the session is in a 
separate class) in order to centralize the operation toward the DB, and 
doing this it should act in a stateless way (createSession, do stuff, 
commit/rollback, close), unfortunately seems that I am missing something.

Thanks
Maurizio



-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/sqlalchemy/-/J4THN4X57aUJ.
To post to this group, send email to sqlalchemy@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.



Re: [sqlalchemy] inheritance + overriding

2011-10-24 Thread Maurizio Nagni
Thanks for the quick and detailed reply but I guess that I should add a 
further information to the discussion. Probably I tried to simplify too 
much the problem...


The mapping that I have is generated automatically from a multiple 
number of UML models. I knew the doc you mention 
(http://www.sqlalchemy.org/docs/orm/inheritance.html ) but if I 
correctly read your doc it is not enough for my needs. I used the join 
approach because in many cases I have a python class inheriting from 
multiple classes so I followed (with some update to manage events) 
your previous discussion here


http://markmail.org/message/ulonbk3hd2rwzzhh#query:sqlalchemy%20multiple%20inheritance+page:1+mid:66l5tgf737nejqis+state:results

---

mapper(CI_OnlineResource, ci_onlineresource_table)

mapper(MO_OnlineResource, mo_onlineresource_table.join(ci_onlineresource_table))

def MO_OnlineResource_before_insert_listener(mapper, connection, target):

target.ci_onlineresource_type = 'mo_onlineresource'

event.listen(MO_OnlineResource, 'before_insert', 
MO_OnlineResource_before_insert_listener)

--

I used also the approach in

http://www.sqlalchemy.org/docs/orm/mapper_config.html#naming-columns-distinctly-from-attribute-names

changing

mo_onlineresource_table = Table('mo_onlineresource', metadata,
Column('mo_onlineresource_id', Integer, 
Sequence('mo_onlineresource_id_seq'), primary_key=True),
Column('function', MO_OnLineFunctionValue.db_type(), nullable=False),
Column('applicationProfile', MO_ApplicationProfileValue.db_type(), 
nullable=False),
Column('mo_onlineresource_type', String(30), nullable=False),
extend_existing=False,)

to

mo_onlineresource_table = Table('mo_onlineresource', metadata,
Column('mo_onlineresource_id', Integer, 
Sequence('mo_onlineresource_id_seq'), primary_key=True),
Column('mo_function', MO_OnLineFunctionValue.db_type(), nullable=False),
Column('mo_applicationProfile', MO_ApplicationProfileValue.db_type(), 
nullable=False),
Column('mo_onlineresource_type', String(30), nullable=False),
extend_existing=False,)


and changing

mapper(MO_OnlineResource, mo_onlineresource_table.join(ci_onlineresource_table))

to

mapper(MO_OnlineResource, 
mo_onlineresource_table.join(ci_onlineresource_table), properties={

   'applicationProfile': mo_onlineresource_table.c.mo_applicationProfile,

   'function': mo_onlineresource_table.c.mo_function

 })


but the result is 99% the same

sqlalchemy.exc.InvalidRequestError: Implicitly combining column 
mo_onlineresource.mo_applicationProfile with column 
ci_onlineresource.applicationProfile under attribute 'applicationProfile'.  
Please configure one or more attributes for these same-named columns explicitly.




On 24/10/11 17:25, Michael Bayer wrote:

On Oct 24, 2011, at 11:43 AM, mnagni wrote:


class CI_OnlineResource(object):
def __init__(self):
super(CI_OnlineResource, self).__init__()
self.applicationProfile = None
self.function = None

class MO_OnlineResource(CI_OnlineResource):
def __init__(self):
super(MO_OnlineResource, self).__init__()
self.function = None
self.applicationProfile = None

mapper(CI_OnlineResource, ci_onlineresource_table)
mapper(MO_OnlineResource,
mo_onlineresource_table.join(ci_onlineresource_table))


the above configuration isn't correct - you'd want to use SQLAlchemy's provided 
joined table inheritance feature:

mapper(MO_OnlineResource, mo_onlineresource_table, inherits=CI_OnlineResource)

docs: http://www.sqlalchemy.org/docs/orm/inheritance.html


The same-named columns will be rolled under one attribute on the subclass, with 
the subclass-table column referenced first.  This is the default behavior.  To 
map the applicationProfile columns distinctly, so that they retain separate 
values, link them each to uniquely named attributes as described at 
http://www.sqlalchemy.org/docs/orm/mapper_config.html#naming-columns-distinctly-from-attribute-names.

The technique to manually roll columns from a join under an attribute for a 
mapping to a join is at:

http://www.sqlalchemy.org/docs/orm/mapper_config.html#mapping-a-class-against-multiple-tables

however when using joined table inheritance these details are handled for you.






the two classes contains the same attributes (function,
applicationProfile) because in my specifications is required that
1) MO_OnlineResource.applicationProfile is a String
2) MO_OnlineResource.applicationProfile is an ENUM of String type

So at this moment I have

mo_onlineresource_table = Table('mo_onlineresource', metadata,
Column('mo_onlineresource_id', Integer,
Sequence('mo_onlineresource_id_seq'), primary_key=True),
Column('function', MO_OnLineFunctionValue.db_type(), nullable=False),
Column('applicationProfile', MO_ApplicationProfileValue.db_type(),