Kent wrote:
> Thank you again for your response and time.
>
> I think a different approach may be better for me, but was hoping for
> your input.
>
> I think I'd like to let session.merge() work out whether it is going
> to do an add() vs. update properties on the object retrieved
> from .get()
>
> Then, after merge(), but before the flush(), I can change anything I
> need/run validations and populate primary keys, etc.
> Then I can call flush().
>
> I think this approach should work for me, but here is my question:
> When merge() returns the merged object, how can I tell whether a
> new_instance was created vs get() having returned an existing object?

"obj in session.new"

>
> Can I inspect the object (and its children) to find this out?  (Am I
> really wondering if this object is persistent? How do I determine
> this?) Or can I inspect the session to determine this?
>
> Can I tell which children are "scheduled" for deletion by inspecting
> the session or merged object somehow?

"obj in session.deleted"

>
> Lastly, by the time merge() returns, we have no reference any longer
> to the original data, only the merged data.  If, for my validations, I
> wanted to compare the old property to the new property, can you
> recommend an approach to this?  I'd rather not hit the database twice,
> since merge is going to look up the data anyway.

whatever Python state you send into merge() remains unchanged.   the "new"
data is what is returned. So you could compare those two things. 
Alternatively, whats returned also represents in itself a "diff" of the
data you passed into merge vs. what was already in the DB.  So if you
wanted to look at individual attributes on the newly merged objects to see
what changed:

from sqlalchemy.orm import attributes
history = attributes.get_history(instance, "somekey")

this returns a tuple of (new, unchanged, deleted).   For a scalar, each
member is a one-item tuple.

>
> I was hoping I might be able to extend Session or override its
> behavior so as to keep a copy of the object returned from .get()
> before it merges the changes.
>
> Input and ideas for me?
>
> Thanks very much in advance,
> Kent
>
>
>
>
> On Feb 6, 5:47 pm, Michael Bayer <mike...@zzzcomputing.com> wrote:
>> On Feb 6, 2010, at 2:16 PM, Kent wrote:
>>
>>
>>
>> > There might/probably is a better way to achieve what I am trying to
>> > achieve.  Let me explain:
>>
>> > I've got a typical Customer/Order/Orderdetail relation.
>>
>> > merge() appeals to me because it does most all the same work I'd
>> > otherwise need to do.  I get passed to me an "Order" object will the
>> > customer object and the details objects.
>>
>> > Now, when I run merge, if there are any changes to the customer, these
>> > get automagically updated.  If a line is missing, it is automatically
>> > deleted.  If a new line exists, it is automatically inserted.
>>
>> > session.merge() does all this.
>>
>> > However, the above is a bit too simplified.  If the Customer's primary
>> > key is not supplied, I need to create this in a special way (not from
>> > a sequence) and then insert it.  In this case, I don't even want merge
>> > to *attempt* to get() from the database first because if, by chance,
>> > the customerid I construct is already in use, I do not want to
>> > accidentally update that record, I *want* the database to complain on
>> > the INSERT that the primary key already exists.
>>
>> > Same with the order and orderdetails.  If an orderdetail is supplied
>> > to me without a primary key, I would like to choose the next
>> > appropriate primary key and INSERT for that particular record, so that
>> > (if something is messed up or a race condition exists with another
>> > instance of the program choosing the same primary key) I get a
>> > database error instead of merge() accidentally updating that other
>> > record.
>>
>> > I don't want to give up the benefits of merge() by programmatically
>> > figuring this out myself.  In other words, if I add() to the session
>> > all the lines I *know* should be INSERTs then I need to work out all
>> > the other magical things merge() is doing for me (like deleting
>> > missing lines).
>>
>> your primary key generation scheme here requires manual steps - you
>> create a new identifier, then you need to check that it doesnt exist.  
>> merge() and add() won't do this for you, so you do this yourself as
>> needed with your given objects, and assign those identifiers to the
>> objects.   Then you can proceed to merge() them normally.  There is no
>> "trick" that will do this for you.
>>
>>
>>
>> > I tried seeing what would happen if I just called session.add() for
>> > the cases of an INSERT and then calling session.merge() for the entire
>> > cascading order(customer/details), but when I tried that I got:
>> > New Instance conflicts with persistent instance type error.
>>
>> > I assume this means: you tried to session.add() and object and now I
>> > just looked up this same instance during the session.merge().
>>
>> unless I'm forgetting something (possible), merge() should not be able
>> to produce that error, since it is not placing any new instances in the
>> session unless that identity did not exist.   Did you turn off autoflush
>> perhaps ?  a flush needs to occur after your add() so that the pending
>> object now becomes persistent (this is why Session does its work in a
>> transaction, in case you're concerned about "writes").
>
> --
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To post to this group, send email to sqlalch...@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.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@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.

Reply via email to