2013-05-31 4 views
0

Dans mon application, j'utilise SQLAlchemy pour stocker les données les plus persistantes dans les redémarrages d'applications. Pour cela j'ai un db contenant mes classes de mappeur (comme Tag, Group etc.) et une classe de support créant une instance de moteur unique utilisant create_engine et une seule usine globale Session utilisant sessionmaker. Maintenant, ma compréhension de l'utilisation des sessions SQLAlchemys est que je ne les passe pas dans mon application mais que je crée des instances en utilisant la fabrique globale chaque fois que j'ai besoin d'un accès à une base de données.Problème avec plusieurs sessions

Cela conduit à des situations où un enregistrement est interrogé dans une session, puis transmis à une autre partie de l'application, qui utilise une instance de session différente. Cela me donne des exceptions comme celle-ci:

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') 

Maintenant, ma question est la suivante: ai-je l'utilisation de Session mal completly (donc je dois utiliser une seule session à la fois et passer cette session autour d'autres composants ainsi que enregistrements de la base de données) ou cela peut-il résulter d'un problème de code réel?

quelques exemples de code montrant mon problème exact:

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) 

Répondre

0

Pour l'instant je suis passé à l'aide d'une seule instance globale de la session. Ce n'est ni agréable ni propre à mon avis, mais inclure beaucoup de code de plaque de chaudière pour effacer les objets d'une session juste pour les ajouter à leur session d'origine après l'avoir transféré à une autre partie de l'application n'était pas réaliste non plus.

Je suppose que cela va complètement exploser si je commence à utiliser plusieurs threads pour accéder à la base de données via la même session ...

Questions connexes