2012-12-14 35 views
17

Tôi mới sử dụng SQLAlchemy và đã kế thừa một codebase hơi lộn xộn mà không cần truy cập vào tác giả gốc.Khi nào tôi nên gọi flush() trên SQLAlchemy?

Mã được bật lên với các cuộc gọi đến DBSession.flush(), dường như bất kỳ lúc nào tác giả muốn đảm bảo dữ liệu đã được lưu. Lúc đầu, tôi chỉ theo dõi các mẫu mà tôi đã thấy trong mã này, nhưng khi tôi đang đọc tài liệu, có vẻ như điều này là không cần thiết - việc tự động điền phải được thực hiện. Ngoài ra, tôi đã nhận được vào một vài trường hợp với các cuộc gọi AJAX tạo ra lỗi "InvalidRequestError: Session đã được flushing".

Trong những trường hợp nào tôi muốn giữ lời gọi tuôn ra()?

Đây là một ứng dụng Kim tự tháp, và SQLAlchemy đang được thiết lập với:

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension(), expire_on_commit=False)) 
Base = declarative_base() 

Trả lời

26

Các ZopeTransactionExtension trên DBSession kết hợp với pyramid_tm những hoạt động trên dự án của bạn sẽ xử lý tất cả các cam kết cho bạn. Các tình huống bạn cần xả là:

  • Bạn muốn tạo đối tượng mới và lấy lại khóa chính.

    DBSession.add(obj) 
    DBSession.flush() 
    log.info('look, my new object got primary key %d', obj.id) 
    
  • Bạn muốn cố gắng thực hiện một số lệnh SQL trong một savepoint và rollback nếu nó không thành công mà không cần hủy bỏ hiệu lực toàn bộ giao dịch.

    sp = transaction.savepoint() 
    try: 
        foo = Foo() 
        foo.id = 5 
        DBSession.add(foo) 
        DBSession.flush() 
    except IntegrityError: 
        log.error('something already has id 5!!') 
        sp.rollback() 
    

Trong mọi trường hợp khác liên quan đến việc ORM, giao dịch sẽ được hủy bỏ cho bạn khi có ngoại lệ, hoặc cam kết khi thành công tự động bởi pyramid_tm. Nếu bạn thực thi SQL thô, bạn sẽ cần tự thực hiện transaction.commit() hoặc đánh dấu phiên là bị bẩn qua zope.sqlalchemy.mark_changed(DBSession) nếu không thì không có cách nào để ZTE biết phiên đã thay đổi.

Bạn cũng nên để lại expire_on_commit theo mặc định là True trừ khi bạn có lý do thực sự tốt.

+0

Cảm ơn rất nhiều. Theo dõi: Điều gì cấu thành một lý do thực sự tốt để có expire_on_commit = Sai trong thiết lập này? (Tôi không biết tại sao nó được thiết lập theo cách này ở nơi đầu tiên). – blocks

+4

Theo kinh nghiệm của tôi, nó được sử dụng bởi những người không biết họ đang làm gì và cố gắng lừa gạt hệ thống bằng cách sử dụng các đối tượng sau khi họ đã được cam kết. * rõ ràng * sau khi cam kết, bạn không có đảm bảo rằng trạng thái của đối tượng đó là hợp lệ nữa. –

+0

@Michael Merickel - Rất được giải thích. Làm thế nào về khi chúng ta không nên sử dụng tuôn ra()? [Có bất kỳ phản ứng phụ nào khi gọi SQLAlchemy flush() trong mã không?] (Http://stackoverflow.com/questions/29338419/are-there-any-side-effects-from-calling-sqlalchemy-flush-within-code) –

Các vấn đề liên quan