Thanks Michael. Always spot on. And I don't think I can find a more authoritative source ;)
On Wed, Dec 19, 2012 at 5:48 PM, Michael Bayer <[email protected]>wrote: > > On Dec 19, 2012, at 4:29 AM, charlax wrote: > > > So the problem here is that the rollback does nothing, because there's a > commit in the delete_password method (in this example there's only method > called, in reality I have multiple methods). I think having stuff being > committed in a model's method is antipattern (is it?) > > > I think it is. I wish I could find more authoritative sources for this > but in my opinion, as well as all the experience I've had with > transaction-aware frameworks, transaction demarcation is specified in the > application in exactly one place, in a position that surrounds all the > business logic. The business logic itself should not have any awareness of > transaction demarcation. > > I've updated the docs significantly to talk about this pattern here: > http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#session-frequently-asked-questions, > in the question "when do I construct a Session?". Web frameworks present > the simplest pattern, but if your application is not a web application, > you'd want to decide on where your app's concept of "business methods" can > be enclosed. > > > but I'd like to know if there's a simple way to get the desired behavior. > I tried: > > > > 1. Manually setting a savepoint (Session.execute("SAVEPOINT > soft_delete")). But commit in delete_password closes the connection so > the savepoint is lost. > 2. Using begin_nested and begin(subtransactions=True), but commit in > delete_password closes the context > > > 1. I thought of using autocommit=True but it seems it's not > recommended (and I'm not sure to understand all the implications of this), > or creating an external > transaction<http://docs.sqlalchemy.org/en/latest/orm/session.html#joining-a-session-into-an-external-transaction> > but > the example in the doc is only for tests so I'm not sure if it's > antipattern too. Also, getting access to the engine would require quite a > small refactor of my app. > > > the subtransaction thing could allow this, if your ad-hoc commit() method > also called begin(subtransactions=True) before it did its work, but this > implies the Session is being used in autocommit mode. > > But there's no reason to use autocommit, while it used to be the default > system of use years ago, now it's only there for certain framework > integrations that want to be able to emit begin() ahead of time. The > Session otherwise shouldn't be used to emit SQL without a transaction > present. > > Which means, there's really no reason in the world you need to call > commit() inside that method, *unless* you're trying to expose that > particular bit of data to the outside world before the enclosing > transaction is complete - and for that use case I'd use a different > transaction altogether. Otherwise, you're already in a transaction that > isn't yet committed, which your app structure should ensure happens before > the larger series of business methods is complete. > > -- > 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. > -- 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.
