Les triggersurs SQL Server et le problème d'interférence sqlalchemy. Besoin d'aide

J'ai besoin d'une sorte de 'versioning' pour certaines tables critiques, et j'ai essayé de l'implémenter de manière plutôt simple:

CREATE TABLE [dbo].[Address] ( [id] bigint IDENTITY(1, 1) NOT NULL, [post_code] bigint NULL, ... ) CREATE TABLE [dbo].[Address_History] ( [id] bigint NOT NULL, [id_revision] bigint NOT NULL, [post_code] bigint NULL, ... CONSTRAINT [PK_Address_History] PRIMARY KEY CLUSTERED ([id], [id_revision]), CONSTRAINT [FK_Address_History_Address]... CONSTRAINT [FK_Address_History_Revision]... ) CREATE TABLE [dbo].[Revision] ( [id] bigint IDENTITY(1, 1) NOT NULL, [id_revision_operation] bigint NULL, [id_document_info] bigint NULL, [description] varchar(255) COLLATE Cyrillic_General_CI_AS NULL, [date_revision] datetime NULL, ... ) 

et un tas de triggersurs sur insert / update / delete pour chaque table, qui est destiné à stocker ses changements.

Mon application est basée sur PyQt + sqlalchemy, et quand j'essaie d'insert une entité, qui est stockée dans une table versionnée, sqlalchemy triggers une erreur:

 The target table 'Heritage' of the DML statement cannot have any enabled sortingggers if the statement contains an OUTPUT clause without INTO clause. (334) (SQLExecDirectW); [42000] [Microsoft][ODBC SQL Server Driver] [SQL Server]Statement(s) could not be prepared. (8180)") 

Que devrais-je faire? Je dois utiliser sqlalchemy. Si on peut me donner un conseil, comment puis-je implémenter le versioning sans triggersurs, ce serait cool.

Vous devez définir 'implicit_returning' sur 'False' pour éviter l'utilisation de 'OUTPUT' dans la requête générée par SQLAlchemy (et cela devrait résoudre votre problème):

 class Company(sqla.Model): __bind_key__ = 'dbnamere' __tablename__ = 'tblnamehere' __table_args__ = {'implicit_returning': False} # http://docs.sqlalchemy.org/en/latest/dialects/mssql.html#sortingggers id = sqla.Column('ncompany_id', sqla.Integer, primary_key=True) ... 

Je ne peux pas sembler append un commentaire en ajoutant une autre réponse.

Ce n'est pas si compliqué et je dirais que c'est less fragile que de mettre la moitié de votre logique métier dans votre domaine et l'autre moitié dans votre database.

Personnellement, j'écrirais mon propre object de list avec une reference à la list d'historique de la list some_list_of_other_entities et dans les methods Remove et Add, je conserverais vos loggings d'historique.

De cette façon, vos objects sont automatiquement mis à jour avant même de les save dans votre ORM.

 public class ListOfOtherEntities : System.Collections.IEnumerable { // Add list stuff here... public void Remove(MyEntity obj) { this.List.Remove(obj); this.History.Add(new History("Added a object!"); } public void Remove(MyEntity obj) { this.List.Remove(obj); this.History.Add(new History("Removed a object!"); } } 

De cette façon, vos objects sont automatiquement mis à jour avant même de les save dans votre ORM et un autre développeur regardant le code peut voir ce que vous avez fait assez facilement.

Cela ne répondra pas directement à votre question, mais dans mon expérience, l'utilisation de Triggers entraîne une douleur sans fin, alors évitez-les à tout prix. Si vous gérez vous-même toutes datatables, la réponse simple est de remplir les tables d'historique des versions. Cela signifie également que vous avez toute la logique de votre entreprise en un seul endroit, ce qui est un bonus!