2011-11-29 1 views
15

Uygulamam, kullanıcıların Site nesnesi oluşturmasına ve silmesine izin verir. Bunu session.add() ve session.delete() kullanarak gerçekleştirdim. Daha sonra session.commit() ve session.rollback()'u arayarak 'Kaydet' ve 'Sıfırla' düğmelerini kullanıyorum.Bir nesneyi kalıcı hale getirilmeden önce bir SQLAlchemy oturumundan silme

Yeni bir Site eklerseniz, kaydet/yapıştır ve sonra sil, her şey yolunda gider. Ancak, kaydedilmeden önce bir nesneyi oturumdan kaldırmaya çalışırsam, 'kalıcı olmayan' bir hata alıyorum.

Kodu:

self.newSite = Site('foo') 
self.session.add(self.newSite) 
print self.session.new 
self.session.delete(self.newSite) 

Çıktı:

IdentitySet([<Site('foo')>]) 

Traceback (most recent call last): 
    File "C:\Program Files\Eclipse\dropins\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc\pydevd_comm.py", line 744, in doIt 
    result = pydevd_vars.evaluateExpression(self.thread_id, self.frame_id, self.expression, self.doExec) 
    File "C:\Program Files\Eclipse\dropins\plugins\org.python.pydev.debug_2.2.1.2011071313\pysrc\pydevd_vars.py", line 375, in evaluateExpression 
    result = eval(compiled, updated_globals, frame.f_locals) 
    File "<string>", line 1, in <module> 
    File "C:\Python27\Lib\site-packages\sqlalchemy\orm\session.py", line 1245, in delete 
    mapperutil.state_str(state)) 
InvalidRequestError: Instance '<Site at 0x1ed5fb0>' is not persisted 

Burada neler olduğunu anlıyorum ama onun yerine yapıyor olması gerektiğinden emin değilim.

Henüz devam etmeyen bir nesneyi bir oturumdan çıkarmak için başka bir yöntem var mı? Veya silmek istediğim nesnenin henüz temizlenmemiş olması durumunda, silme girişiminde bulunmadan önce session.flush() numaralı telefonu arayayım mı?

İkincisiyse, session.query() otomatik temizleme (beklemedeki nesnelerin sorgu sonuçlarında görünmesini sağlar), ancak session.delete() neden olmaz (beklemede olan nesnelerin hatasız olarak silinebilmesini sağlar).

cevap

13

Session.expunge() yapabilirsiniz. Bu şekilde delete() ile mantıklı olduğunu düşünüyorum, beklemede yolladığınız şeyleri takip etmemenizin endişesi. Ama hikayenin diğer tarafını görebiliyorum, bunun hakkında düşüneceğim. Temel olarak, delete() tarafından ima edilen devlet bazı süreklilik varsayımları içerir, ancak muhtemelen düşündüğüm kadar önemli değillerdir. Aklıma gelen "bir" silme veya silme "metodu akla geliyor. Bu, esasen" eklenti "haline gelen Hibernate'den kopyaladığımız" kaydet veya güncelle "komik. "ekleme" geçici -> beklemenin yanı sıra ayrılmamış -> kalıcı geçişlerin geçişlerini yapabilir - potansiyel "çıkar()" hem beklemede -> hem geçici hem de kalıcı -> silinsin mi? Kapsamlı oturumun çok kötüsünün "remove()" zaten vardır. Bazı satırları almak için bazı SQL yayımlamak üzere veritabanına çıkmak üzere olduğu için autoflushes; Yani önce yerel olarak neye ihtiyacınız varsa sahip olmalısınız. delete() sadece bir nesnenin durumunu işaretler, böylece herhangi bir SQL'i çağırmaya gerek yoktur. Beklemede çalışmak için delete() istediğimizde, yalnızca bu onaylamayı değiştiririz. rollback() oturumunda, add() oturumunuz ne olursa olsun, o oturumda, temizlenip temizlenmediğine bakılmaksızın silinir.

+3

Mike ile aynı fikirdeyim ki "sil" daha bağışlayıcı olabilir. Bununla birlikte, mevcut durum çok basitleştirilmiştir - aynı oturuma eklenen ve taahhüt edilmeyen açık veya zımni (ilişkilerle) olan başka ilgili nesneler de olabilir. Bu nedenle, IMO, en temiz yol, oturumda 'rollback()' yapmaktır. – van

+0

Teşekkürler, bu şimdi mantıklı. Silme düğmesine tıklandığında, mantık ne olmalıdır? Denemek gibi bir şey: session.delete (foo); InvalidRequestError: session.expunge (foo) 'dışında? Ya da, [bu cevap] 'a göre (http://stackoverflow.com/a/3897845/665488), belki: eğer has_identity (foo) ise: session.delete (foo); başka: session.expunge (foo) '? –

+5

Muhtemelen "session.new'de nesne varsa: else else: delete" derdim. – zzzeek