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)