2016-04-14 7 views
0

簡単なコード:それはDELOBJ(「インスタンスxxxは保持されません」 SQLAlchemyの:状態管理には、どのセッションでアンシリアライズインスタンスを永続化するよう

iはsession.addしようとしたようにエラーが発生し

import pickle, cPickle 
from app import session, redis 

class MyObj(DeclarativeBase): 
    @classmethod 
    def get(cls,id): 
     key = cls.__name__+":"+str(id) 
     cached = redis.get(key) 
     if cached: 
      # unserialize to cls instance 
      return cPickle.loads(cached) 
     record = session.query(cls).filter(cls.id==id).one() 
     if record: 
      # serialize and store to redis 
      redis.set(key, pickle.dumps(record)) 
     return record 


# first time , a normal orm instance returned from session query (uncached) 
obj = MyObj.get(1) 

# but the next requests, get cached from redis. 
# and i want to delete the record 
delobj = MyObj.get(1) 
session.delete(delobj) 
session.commit() 

)を削除する前に、ペンディング状態はTrue(状態= inspect(delobj))ですが、それでも削除できません。例から

merge() transfers state from an outside object into a new or already existing instance within a session.

答えて

0

あなたは現在のセッションにmergeキャッシュされたインスタンスに必要なので

An application is storing objects in an in-memory cache, shared by many Session objects simultaneously. merge() is used each time an object is retrieved from the cache to create a local copy of it in each Session which requests it. The cached object remains detached; only its state is moved into copies of itself that are local to individual Session objects.

In the caching use case, it’s common to use the load=False flag to remove the overhead of reconciling the object’s state with the database. There’s also a “bulk” version of merge() called merge_result() that was designed to work with cache-extended Query objects - see the section Dogpile Caching .

if cached: 
     # unserialize to cls instance 
     return session.merge(cPickle.loads(cached), load=False) 

持続clsのオブジェクトのみ、またはキャッシュすることを忘れないでくださいエラーが表示されます:

InvalidRequestError: merge() with load=False option does not support objects transient (i.e. unpersisted) objects. flush() all changes on mapped instances before merging with load=False. 

前述のエラーを生成する簡単な方法:

In [63]: obj = MyObj() 

In [64]: session.add(obj) 

In [65]: session.flush() 

In [66]: obj.__dict__ 
Out[66]: 
{'id': 2, 
'_sa_instance_state': <sqlalchemy.orm.state.InstanceState at 0x7fe6f380cac8>} 

In [67]: cached = pickle.dumps(obj) 

In [68]: session.commit() 

In [69]: obj2 = session.merge(pickle.loads(cached), load=False) 

In [70]: obj2 in session 
Out[70]: True 
+0

素晴らしい:あなたが最初に適切にオブジェクトを永続化する一方場合

obj = MyObj() cached = pickle.dumps(obj) obj2 = session.merge(pickle.loads(cached), load=False) ... InvalidRequestError: merge() with load=False option does not support objects transient (i.e. unpersisted) objects. flush() all changes on mapped instances before merging with load=False. 

!できます。しかし、私はload = Falseを使用しています。 Error:merge()with load = Falseオプションは、オブジェクトの一時的(すなわち、固定されていない)オブジェクトをサポートしません。 load = Falseとマージする前に、マップされたインスタンスのすべての変更をflush()します。 – GiveMeFive

+0

キャッシュ内のDBに永続化されていないオブジェクトを何らかの形でキャッシュすることができたようです。キャッシュされたインスタンスの主キーが見つからない場合、[session.py](https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/session.py#L1761)でエラーが発生します... おもう。 [State management](http://docs.sqlalchemy.org/en/latest/orm/session_state_management.html)から: "Transient - セッションにはなく、データベースに保存されていないインスタンス、つまり、データベースのアイデンティティ。 –

+0

私のアプリには2つのhttpリクエストがありました。アクションを挿入し、アクションを削除します。私はレコードを挿入した後に自動的にキャッシュされた@ event.listens_for(cls、 'after_insert')の挿入イベントを聴いています。 2番目のhttpリクエストでは、キャッシュからインスタンスを取得して(キャッシュされている場合)、それを削除します。... load = Falseは機能しません。たぶん理由は2つの異なるhttp要求で動作するということです。 – GiveMeFive

関連する問題