On Dec 9, 2007, at 4:57 PM, Adam Batkin wrote:

> Ahh, but session.save() was already called, so trying to fetch a
> database-generated attribute (such as the primary key in my case)  
> should
> trigger a flush of the row itself. That can be done with any database.
> It wouldn't be done on __init__, nor would it be done on save(). It
> would be done only once you tried to fetch the id property (only for
> objects in the Pending state)
>
> Okay, as an example. Let's say you have:
>
> something_table = Table('something', metadata,
>       Column('id', Integer, primary_key=True),
>       Column('name', String)
> )
>
> class Something(object):
>       def __init__(self,name):
>               self.name = name
>
>       def __repr__(self):
>               return "<Something(%d,'%s')>" % (self.id, self.name)
>
> mapper(Something,something_table)
>
> obj = Something('blah')
> session.save(obj)
> print "Look ma, a something: %s" % obj
>
> In theory that will throw an exception since Something's __repr__ will
> have None for the id property, since id was never retrieved.
>
> (if I just did:
>
> obj = Something('blah')
> print "Bad idea: %s" % obj
>
> then I would expect an exception, since it's not saved)
>
> Does this description make more sense that what I said before?
>

I hate to disagree here, and I can see what you're getting at, but  
honestly, the "INSERT on save()" approach is exactly the naive active- 
record-like pattern that SQLAlchemy's ORM was designed to get away from.

The way the unit of work functions, we dont generate ids until a flush  
occurs.  Flushes dont occur unless you say flush(), or if you have  
autoflush=True in which case they occur right before a query.  Having  
flush() happen automatically for save() would be an enormous change to  
how we've been doing things for quite some time, the implications and  
side effects of which I have not thought through, but i can think of a  
few immediate ones:  it would break compatibility with everyone thats  
using the Session.mapper extension, which saves automatically on  
__init__,  and it would certainly break compatibility with any number  
of existing applications that are calling save() without the  
"autoflush on save" expectation.     But beyond that, it would wreak  
havoc with core features such as cascading...right now, you can  
append() items to a collection, and they are save()d automatically as  
they are added.  By deferring the SQL until a single flush() stage, we  
dont incur the overhead of flush() for every item (which, depending on  
configuration, may include checking out connections, starting/ 
committing transactions, sorting dependencies, etc.); the full graph  
of objects is assembled and *then* flushed - this is the entire point  
of the unit of work pattern, that many changes are pushed into a  
single cohesive transactional event, reducing database traffic,  
avoiding deadlocks, etc.

For the issue above, it seems a whole lot easier to just type  
"Something %r".  I dont see any fundamental issue by the fact that  
primary keys are not immediately present upon save(), and additionally  
if your __repr__ wanted to print out foreign key identifiers as well  
(like many-to-ones), you're back to the same problem again.








--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to