2013-05-31 92 views
0

在我的應用程序中,我使用SQLAlchemy在應用程序重新啓動時存儲大多數持久數據。爲此,我有一個包含我的映射程序類(如Tag,Group等)的db程序包,以及使用create_engine和使用sessionmaker的單個全局Session工廠創建單個引擎實例的支持類。多個會話的問題

現在我對如何使用SQLAlchemys會話的理解是,我不會在應用中傳遞它們,而是在需要數據庫訪問時使用全局工廠創建實例。

這會導致在一個會話中查詢記錄,然後傳遞到應用的另一部分,該應用使用不同的會話實例。這給了我喜歡的例外這一個:

Traceback (most recent call last): 
    File "…", line 29, in delete 
    session.delete(self.record) 
    File "/usr/lib/python3.3/site-packages/sqlalchemy/orm/session.py", line 1444, in delete 
    self._attach(state, include_before=True) 
    File "/usr/lib/python3.3/site-packages/sqlalchemy/orm/session.py", line 1748, in _attach 
    state.session_id, self.hash_key)) 
sqlalchemy.exc.InvalidRequestError: Object '<Group at 0x7fb64c7b3f90>' is already attached to session '1' (this is '3') 

現在我的問題是:我纔拿到的使用Session完全地錯誤的(所以我應該一次只使用一個會話和周圍一起傳遞會話到其他部件來自數據庫的記錄),還是可能由實際的代碼問題導致?

一些示例代碼演示我確切的問題:

from sqlalchemy import create_engine, Column, Integer, String 
from sqlalchemy.orm import sessionmaker 
from sqlalchemy.ext.declarative import declarative_base, declared_attr 

Base = declarative_base() 

class Record(Base): 
    __tablename__ = "record" 

    id = Column(Integer, primary_key=True) 
    name = Column(String) 

    def __init__(self, name): 
     self.name = name 

    def __repr__(self): 
     return "<%s('%s')>" % (type(self).__name__, self.name) 

engine = create_engine("sqlite:///:memory:") 
Base.metadata.create_all(engine) 

Session = sessionmaker(bind=engine) 

s1 = Session() 

record = Record("foobar") 
s1.add(record) 
s1.commit() 

# This would be a completly different part of app 

s2 = Session() 

record = s2.query(Record).filter(Record.name == "foobar").first() 

def delete_record(record): 
    session = Session() 
    session.delete(record) 
    session.commit() 

delete_record(record) 

回答

0

現在我切換到使用一個單一的,全局會話實例。在我看來,這既不好也不乾淨,但包括很多大量的鍋爐板代碼以將一個會話中的對象從一個會話中刪除,然後將它們交給其他應用程序部分後再添加回原來的會話也是不現實的選擇。

我想這將完全炸燬,如果我開始使用多個線程訪問數據庫通過相同的會話...