Marble wrote:
>
>> > Can someone help me to get this right?
>>
>> this is ticket 1362 and is a
>> TODO:http://www.sqlalchemy.org/trac/ticket/1362.
>
> My fault, I should have checked the tickets before posting.
>
>> For now you need to issue update() statements for the tables
>> manually,then reload your objects.
>>
>
> Waiting for the new release with the issue fixed might not be an
> option (unless it is planed very soon:). However, manually updating
> tables at different locations in the code does not seem a good
> alternative either.
>
> For that reason I considered to update the table in a
> SessionExtension. The extension, as shown below, updates the table at
> the database level before a flush(). As I understand the documentation
> a refresh reloads the object incorporating the changes. Now if I
> continue to work with the object instance, I get an
> ObjectDeletedError. Could you once more help me to understand what is
> going on and how I can fix this?
you get an ObjectDeletedError because the primary key of an object has
changed in the database, but SQLA's internal accounting of this attribute
is stale, pointing to the old value. This is why its necessary to
completely reload the objects if you manipulate the database directly.
The object has a stale key which is present at
instance._sa_instance_state.key, and that key is also in the Session's
identity_map with that stale key - the internal accounting updates both of
these conditions when a primary key switch is detected. this accounting
occurs within unitofwork/UOWTransaction.finalize_flush_changes(). In the
case of joined table inheritance, extra awareness of primary key changes
needs to be built into mapper._save_obj() to handle propagation of new pk
values to child tables, and likely some other tweaks to handle the
operation across subclasses.
Just as an FYI I work with an app that has extensive joined table
inheritance in use and we have a lot of primary key mutation going on -
the scripts that deal with PK mutation perform these updates outside of
the scope of ORM level operations. I've been able to work around the
lack of this feature so far but I do want to get around to implementing.
>
> Thanks a lot.
>
>
> class UpdateExt(SessionExtension):
> def before_flush(self, session, flush_context,instances):
> for employee in session.dirty:
> if isinstance(employee, Employee):
> table = Table('employees', base.metadata,
> autoload=True)
> upd = table.update(values={'name': employee.name})
> base.metadata.bind.execute(upd)
> session.refresh(employee, ['name'])
>
> #============================
> Session = sessionmaker(extension=UpdateExt())
> session = Session()
> joe = Engineer('Joe','Engineer of the month')
> session.add(joe)
> session.commit()
> joe.name = 'Joey'
> session.commit() #Changes persistent in the database, no Error
> print joe.name #ObjectDeletedError
>
>
> >
>
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected]
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
-~----------~----~----~----~------~----~------~--~---