Ho un modello/tabella Test
e un modello/tabella TestAuditLog
, utilizzando SQLAlchemy e SQL Server 2008. La relazione tra i due è Test.id == TestAuditLog.entityId
, con un test con molti audit log. TestAuditLog
è progettato per conservare una cronologia delle modifiche alle righe nella tabella Test
. Voglio tenere traccia quando viene eliminato anche uno Test
, ma ho problemi con questo. In SQL Server Management Studio, ho impostato la proprietà "Enforce Foreign Key Constraint" della relazione FK_TEST_AUDIT_LOG_TEST
su "No", pensando che consentirebbe a una riga TestAuditLog
di esistere con uno che non si connette più a qualsiasi Test.id
perché il Test
è stato eliminato. Tuttavia, quando cerco di creare un TestAuditLog
con SQLAlchemy e quindi eliminare il Test
, ottengo un errore:SQLAlchemy: non applicare il vincolo di chiave esterna a una relazione
(IntegrityError) ('23000', "[23000] [Microsoft][ODBC SQL Server Driver][SQL Server]Cannot insert the value NULL into column 'AL_TEST_ID', table 'TEST_AUDIT_LOG'; column does not allow nulls. UPDATE fails. (515) (SQLExecDirectW); [01000] [Microsoft][ODBC SQL Server Driver][SQL Server]The statement has been terminated. (3621)") u'UPDATE [TEST_AUDIT_LOG] SET [AL_TEST_ID]=? WHERE [TEST_AUDIT_LOG].[AL_ID] = ?' (None, 8)
penso a causa del rapporto di chiave esterna tra Test
e TestAuditLog
, dopo aver eliminare la riga Test
, SQLAlchemy sta tentando di aggiornare tutti i registri di controllo di quel test per avere un . Non voglio che lo faccia; Voglio che SQLAlchemy lasci da solo i registri di controllo. Come posso dire a SQLAlchemy di consentire l'esistenza di registri di controllo di cui entityId
non si connette con qualsiasi Test.id
?
ho provato solo la rimozione della ForeignKey
dai miei tavoli, ma mi piacerebbe essere ancora in grado di dire myTest.audits
e ottenere tutti i registri di controllo di un test, e SQLAlchemy lamentavano di non sapere come partecipare Test
e TestAuditLog
. Quando ho quindi specificato uno primaryjoin
su relationship
, si è lamentato di non avere uno ForeignKey
o ForeignKeyConstraint
con le colonne.
Qui sono i miei modelli:
class TestAuditLog(Base, Common):
__tablename__ = u'TEST_AUDIT_LOG'
entityId = Column(u'AL_TEST_ID', INTEGER(), ForeignKey(u'TEST.TS_TEST_ID'),
nullable=False)
...
class Test(Base, Common):
__tablename__ = u'TEST'
id = Column(u'TS_TEST_ID', INTEGER(), primary_key=True, nullable=False)
audits = relationship(TestAuditLog, backref="test")
...
Ed ecco come sto cercando di eliminare un test, mantenendo i suoi registri di controllo, la loro entityId
intatte:
test = Session.query(Test).first()
Session.begin()
try:
Session.add(TestAuditLog(entityId=test.id))
Session.flush()
Session.delete(test)
Session.commit()
except:
Session.rollback()
raise
Il 'passive_deletes = 'all'' sulla' relazione' l'ha fatto!In questo modo sono riuscito a mantenere le relazioni e SQLAlchemy non è tornato indietro e ho cercato di cancellare "entityId' in" Test ". Grazie! –
Solo per il riferimento - sarebbe necessario anche impostare 'lazy =" dynamic "' sul lato genitore della relazione in modo che sqlalchemy non recuperi tutti i child quando non ne hai bisogno (cioè quando aggiorna solo un campo non pertinente nella tabella padre). – Greg0ry
@ Greg0ry: No, non è necessario. Come documentato in [Uso delle strategie di caricamento: Caricamento lento, Caricamento in carico] (http://docs.sqlalchemy.org/en/rel_1_0/orm/loading_relationships.html#using-loader-strategies-lazy-loading-eager-loading): * Per impostazione predefinita, tutte le relazioni tra oggetti sono lazy loading ... *. Quindi, a meno che tu non faccia altrimenti, il genitore non dovrebbe caricare i bambini a meno che tu non li acceda. – van