2016-04-14 10 views
0

basit kod: o delobj ("örneği xxx kalıcıdır değil" sqlalchemy: Devlet Yönetimi, nasıl oturumda bir unserialize örneğini devam etmek gibi

i session.add çalıştı gibi bir hata yükseltmek

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

) silmeden önce, Beklemede durumu doğrudur (durum = denetle (delobj)), ancak yine de silmek için çalışmaz. örneklerden

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

:

cevap

0

Geçerli oturuma merge önbelleğe örneklerine ihtiyaç Yani

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) 

devam cls ait nesneler yalnızca veya önbelleğe hatırla hatayı alırsınız:

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. 

yukarıda belirtilen hata üretmek için basit bir yolu:

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

müthiş: İlk düzgün nesne devam Öte yandan eğer

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. 

! işe yarıyor. ama yük = false kullansaydım. Yük yükseltiyor: yük ile birleştirme() = yanlış seçeneği nesneleri geçici (yani, dağıtılmamış) nesneleri desteklemiyor. load = false ile birleştirmeden önce eşlenen örneklerde tüm değişiklikleri temizleyin(). – GiveMeFive

+0

Bir şekilde, önbelleğinizdeki DB'ye kalıcı olmayan nesneleri önbelleğe almayı başarmışsınız gibi görünüyor. Önbelleğe alınan örneğiniz için birincil anahtar bulamadığında bu hata [session.py] (https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/orm/session.py#L1761) adresinde oluşturulur. ... Bence. [Devlet yönetimi] 'den (http://docs.sqlalchemy.org/en/latest/orm/session_state_management.html): "Geçici - bir oturumda olmayan ve veritabanına kaydedilmeyen bir örnek; veritabanı kimliği. " –

+0

, uygulamanızda iki tane http isteği vardı. eylem eklemek ve eylemi silmek. insert event @ event.listens_for (cls, 'after_insert'), bir kayıt eklendikten sonra otomatik olarak önbelleğe aldım. ve ikinci http isteği, önbellekten (önbelleğe alınmışsa) silme işlemini gerçekleştirir ... ve load = False çalışmaz. Belki de iki farklı http isteğinde çalıştıklarıdır. – GiveMeFive